2014-02-06 29 views
0

,如果我有这些文档:MongoDB的索引范围发现

{"name": 1, "score": 2} 
{"name": 1, "score": 4} 
{"name": 2, "score": 2} 
{"name": 2, "score": 4} 

如果我保证指数:

db.test.ensureIndex({"name":1, "score":1}) 

然后我试图找到():

db.test.find({"score": 4}) 

我用explain(),并发现这个查询不能使用索引,它会扫描所有的四个文档。

我不知道为什么它会扫描所有的文档?

你知道,如果我枚举所有的“名”的值(1和2):

db.test.find({"$or":["name":1, "name":2], "score":4}) 

它可以使用索引,只扫描的两个文档。

为什么mongodb无法为我做这件事?

+1

你不应该使用$或当两个子句有相同的字段。改用{name:{$ in:[1,2]}}。 –

回答

1

不使用索引的原因是因为$or排除运营商,这意味着,以确定什么是比赛或多或少扫描的一切。

你真正想使用的是$in。这将减少匹配到只有包含在该集合中的那些值。

db.test.find({"$in":["name":1, "name":2], "score":4}) 

由于这是包容那场比赛可以被应用于索引没有做一个完整的扫描。

0

一般的经验法则是:如果你有一个综合指数,你通过一个字段从它可以搜索,你还必须指定所有字段到它在索引定义左边。

你能想到的综合指数的这种方式:文档被索引/由第一场分组,然后,这些群体中,他们是由第二场索引。

所以,当你试图通过第二场进行搜索,不指定第一个,蒙戈将要扫描整个索引,因为它不能有效地从穿越排除项目。

db.test.find({"name": {"$in": [1, 2]}, "score": 4}) 

在这种情况下,它只会查看name = 1和name = 2索引条目并在那里查找score = 4。如果您不指定名称,它将扫描所有内容。这不是非常有效。

0

在MongoDB中,如果有关于收集一个复合索引(如您的收藏中的情况下,复合索引是(姓名,分数)),索引字段的顺序是非常重要的。 MongoDB只能将复合索引用于包含索引字段前缀的查询。所以,在你的情况下,索引将只针对查询,其中包括:
1)姓名字段
2)姓名和分数字段。

对于任何其他查询,索引将不会被使用。这是因为mongoDB创建复合索引的方式。文件将首先通过名称字段索引,然后通过分数字段索引。如果查询仅包含分数字段,那么mongoDB无法使用索引来查找文档。

参考:http://docs.mongodb.org/manual/core/index-compound/#compound-index-prefix