【问题标题】:mongodb index range findmongodb索引范围查找
【发布时间】:2014-02-06 06:07:20
【问题描述】:

如果我有这些文档:

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

如果我确保索引:

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

然后我尝试 find():

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

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

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

你知道,如果我枚举所有 "name" 的值(1 和 2):

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

它可以使用索引并且只扫描两个文档。

为什么 mongodb 不能为我做这件事?

【问题讨论】:

  • 当两个子句具有相同的字段时,您不应该使用 $or。请改用 { name : { $in : [ 1, 2 ] } }。

标签: mongodb indexing mongodb-query


【解决方案1】:

没有使用您的索引的原因是因为$or 是一个排除 运算符,这意味着它或多或少会扫描所有内容以确定什么是不是 一场比赛。

你真正想要使用的是$in。这会将匹配减少为包含在集合中的那些值。

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

由于这是包容性,因此可以将匹配应用于索引而无需进行完整扫描。

【讨论】:

    【解决方案2】:

    在 mongoDB 中,如果集合上有复合索引(如你的集合中的情况,复合索引是 (name, score)),索引字段的顺序非常重要。 MongoDB 只能将复合索引用于包含索引字段前缀的查询。因此,在您的情况下,索引仅适用于包含以下内容的查询:
    1) 名称字段
    2) 名称和分数字段。

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

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

    【讨论】:

      【解决方案3】:

      一般的经验法则是这样的:如果您有一个复合索引并通过其中的一个字段进行搜索,您还必须在索引定义中指定它左侧的所有字段。

      您可以这样想复合索引:文档由第一个字段索引/分组,然后在这些组中,它们由第二个字段索引。

      因此,当您尝试按第二个字段而不指定第一个字段进行搜索时,mongo 将不得不扫描整个索引,因为它无法有效地从遍历中排除项目。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多