【问题标题】:How does MongoDB handle compound indexes of object properties nested in an array?MongoDB 如何处理嵌套在数组中的对象属性的复合索引?
【发布时间】:2013-02-15 12:25:11
【问题描述】:

我明白Compound Multikey Indexes May Only Include One Array Field

以下不会产生“无法索引并行数组”错误:

db.test.ensureIndex({"values.x": 1, "values.y": 1})

db.test.insert({"values": [ {"x": 1, "y": 2}, {"x": 2, "y": 2} ]})
db.test.insert({"values": [ {"x": 2, "y": 1}, {"x": 1, "y": 1} ]})
db.test.insert({"values": [ {"x": 1, "y": 1}, {"x": 1, "y": 1} ]})

因此,在对象嵌套在一个数组字段中的多个对象属性上,似乎允许复合索引。

文档说“MongoDB 分别索引数组中的每个值”,因此对于上述场景,我希望为每个文档中的 values.x 和 values.y 的所有组合创建索引条目。

但是,以下对两个嵌套字段的查询表明仅使用复合索引中的第一个字段 - nscanned 为 2,这表明 Mongo 必须检查第二个添加的文档以检查数组元素上的 y = 2匹配 x = 2。

db.test.find({"values.x": 2, "values.y": 2}).explain()
{
    "cursor" : "BtreeCursor values.x_1_values.y_1",
    "isMultiKey" : true,
    "n" : 1,
    "nscannedObjects" : 2,
    "nscanned" : 2,
    "nscannedObjectsAllPlans" : 2,
    "nscannedAllPlans" : 2,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
            "values.x" : [
                    [
                            2,
                            2
                    ]
            ],
            "values.y" : [
                    [
                            {
                                    "$minElement" : 1
                            },
                            {
                                    "$maxElement" : 1
                            }
                    ]
            ]
    },
    "server" : "localhost:27017"
}

MongoDB 索引什么,复合索引对只覆盖第一个字段的值有什么影响?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    如果您使用$elemMatch 查询运算符在同一元素中搜索xy 值,您会看到索引边界也适用于y

    > db.test.find({ values: { $elemMatch: { x: 2, y: 2 }}}).explain()
    {
        "cursor" : "BtreeCursor values.x_1_values.y_1",
        "isMultiKey" : true,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
            "values.x" : [
                [
                    2,
                    2
                ]
            ],
            "values.y" : [
                [
                    2,
                    2
                ]
            ]
        },
        "server" : "localhost:27017"
    }
    

    这是在 SERVER-3104 中为 2.4 实现的。票证说明解释了为什么这些索引范围不能用于您的原始查询:

    在为多个字段创建复合索引时,Mongo 不会计算笛卡尔积。如果文档{ a:[ { b:1, c:2 }, { b:10, c:20 } ] }根据索引{ 'a.b':1, 'a.c':1 }进行索引,则 创建的索引键是{ '':1, '':2 }{ '':10, '':20 }。 (例如没有索引键 { '':1, '':20 }。)

    现在,假设我们有一个查询 { 'a.b':1, 'a.c':20 }。该查询应该与文档匹配,因为文档中存在 'a.b' 值为 1,而文档中存在 'a.c' 值为 20。但是,没有索引键在“a.b”位置包含 1,在“a.c”位置包含 20。因此,“a.b”上的索引边界将是[[ 1, 1 ]],但“a.c”上不会有任何索引边界。这意味着将检索索引键{ '':1, '':2 } 并用于查找完整文档,Matcher 将确定完整文档与查询匹配

    【讨论】:

      猜你喜欢
      • 2016-11-25
      • 2019-09-03
      • 2018-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多