了解子文档数组的索引

Posted

技术标签:

【中文标题】了解子文档数组的索引【英文标题】:Understanding an index on an array of subdocuments 【发布时间】:2012-11-14 23:56:37 【问题描述】:

我一直在研究 MongoDB 上的数组(多键)索引,并且我有以下问题,但我无法找到很多文档:

子文档数组的索引

所以如果我有一个看起来像这样的数组字段:

field : [
  a : "1", 
  b : "2", 
  c : "3"
  ]

我只单独查询field.afield.c(不是同时查询),我相信我可以在以下备选方案中进行选择:

    db.Collection.ensureIndex(field : 1); db.Collection.ensureIndex(field.a : 1); db.Collection.ensureIndex(field.c : 1);

即:对整个数组的索引;或嵌入字段上的两个索引。现在我的问题是:

如何在选项 1 中可视化整个数组的索引(它甚至有用)?这样的索引对哪些查询有用? 鉴于我描述的查询情况,以上两个选项哪个更好,为什么?

【问题讨论】:

+1 表示格式正确的问题。 @Aid 你最后做了什么?结果如何? @Kevin 对于这个特定的查询选项 2 效果更好。如果要查询数组全部内容的等价性,选项 1 更好。 谢谢,@Zaid。对不起,我拼错了你的名字。顺便说一句,如果您的数组具有相同的字段名称,您是否能够对整个 fields 数组进行索引?示例:field : [a : "1", a : "2", a : "3"]?请注意,每个数组的 JSON 对象都包含一个 a 字段。 【参考方案1】:

您说得对,如果您只查询字段数组中 a 的值,那么从某种意义上说,这两个索引都会帮助您提高查询的性能。

但是,请查看以下 3 个查询:

> db.zaid.save(field : [a: 1, b: 2, c: 3] );
> db.zaid.ensureIndex(field:1);
> db.zaid.ensureIndex("field.a":1);

#Query 1
> db.zaid.find("field.a":1)
 "_id" : ObjectId("50b4be3403634cff61158dd0"), "field" : [  "a" : 1 ,  "b" : 2 ,  "c" : 3  ] 
> db.zaid.find("field.a":1).explain();

    "cursor" : "BtreeCursor field.a_1",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 1,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : 
        "field.a" : [
            [
                1,
                1
            ]
        ]
    


#Query 2
> db.zaid.find("field.b":1).explain();

    "cursor" : "BasicCursor",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : 

    


#Query 3
> db.zaid.find("field":b:1).explain();

    "cursor" : "BtreeCursor field_1",
    "nscanned" : 0,
    "nscannedObjects" : 0,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : 
        "field" : [
            [
                
                    "b" : 1
                ,
                
                    "b" : 1
                
            ]
        ]
    

请注意,即使您为数组编制了索引,第二个查询也没有索引,但第三个查询却有。根据您打算如何查询数据来选择索引与考虑索引本身是否是您需要的一样重要。在 Mongo 中,如果您不小心,您的索引结构可以并且确实会对查询的性能产生非常大的影响。我认为这可以解释您的第一个问题。

您的第二个问题比较开放,但我认为答案再次在于您希望如何查询数据。如果您只对匹配“fields.a”的值感兴趣,那么您应该为将来可能需要的其他索引节省内存空间。但是,如果您同样可能查询数组中的任何这些项目,并且您有理由确定数组不会无限增长(永远不要对可能会随着时间增长到无限大小的数组进行索引。索引一旦数组在 BSON 中达到 1024 个字节,将无法索引文档。),那么您应该索引整个数组。这方面的一个例子可能是一手扑克牌的文档,其中包含描述用户手中每张牌的数组。您可以在此数组上进行索引,而不必担心超出索引大小边界的溢出,因为一手牌永远不会超过 52 张。

【讨论】:

这是否意味着如果我的数组会变大,我仍然可以使用“fields.a”对其进行索引?或者我不应该以任何形式索引一个不断增长的数组?

以上是关于了解子文档数组的索引的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB 高级索引

获取数组中每个索引的子文档元素计数并更新子文档键 - 数组中的子文档(IN MONGODB)

PostgreSQL 可以索引数组列吗?

MongoDB索引

Firestore删除一个数组内的索引

MongoDB $and 仅当 $and 在文档的同一数组索引中为真时才查询 - 特别是对于双重嵌套数组 [重复]