让我们考虑一个包含一组嵌入文档的文档:
{ _id: 1, arr: [ { fld1: "x", fld2: 43 }, { fld1: "r", fld2: 80 } ] }
我创建了一个索引arr.fld1
;这是一个多键索引(数组上的索引就是这样调用的)。该_id
字段已具有默认唯一索引。
以下查询使用两个字段上的索引 -arr.fld1
和_id
. 使用查询生成的查询计划explain()
显示了两个字段的索引扫描 (IXSCAN)。
db.test.find( { $or: [ { _id: 2 }, { "arr.fld1": "m" } ] } )
现在同样的查询过滤器也用于更新操作。因此,我们将两个子文档添加到数组的更新:
db.test.update(
{ $or: [ { _id: 1 }, { "arr.fld1": "m" } ] },
{ $addToSet: { arr: { $each: [ { "fld1": "xx" }, { "fld1": "zz" } ] } } }
)
同样,查询计划显示两个索引都用于更新操作。请注意,我没有使用find或update查询的提示。
我无法就您的代码或索引的问题得出结论(请参阅下面的注释:1)。
笔记:
- 上述观察结果基于在MongoDB 服务器 4.0 版上运行的查询(据我所知,也适用于3.6 版)。
- 解释方法
用于查找和更新:
db.collection.explain().find( ... )
和
。
db.collection.explain().update( ... )
- 请注意,您不能使用for
方法生成查询计划;它仅适用于和
方法。您可以使用mongo shell中的命令获取可以生成查询计划的方法列表:
。
explain()
updateOne
findAndModify()
update()
db.collection.explain().help()
Java代码注意事项:
使用多个子文档添加更新数组字段的 Java 代码如下:
collection.updateOne(
or(eq("_id", new Integer(1)), eq("arr.fld1", "m")),
addEachToSet("arr", Arrays.asList(new Document("fld1", "value-1"), new Document("fld1", "value-2"))
);