首页 > 解决方案 > 设置更新提示以使用索引

问题描述

根据文档,可以提供更新提示。
现在我正在使用 java mongo 客户端和 mongo 集合进行更新。

对于此更新,我找不到任何方法来提示要使用哪个索引。
我看到更新我正在日志中进行 COLSCAN,所以想提供提示。

this.collection.updateOne(
    or(eq("_id", "someId"), eq("array1.id", "someId")),
    and(
        addToSet("array1", new Document()),
        addToSet("array2", new Document())
    )
);

两者都有索引_idarray1.id 我在日志中发现此更新的查询使用 COLSCAN 来查找文档。

谁能指出我正确的方向?

使用 AWS DocumentDB,即 MongoDB v3.6

标签: mongodb-javaaws-documentdb-mongoapi

解决方案


让我们考虑一个包含一组嵌入文档的文档:

{ _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" } ] } } }
)

同样,查询计划显示两个索引都用于更新操作。请注意,我没有使用findupdate查询的提示。

我无法就您的代码或索引的问题得出结论(请参阅下面的注释:1)。


笔记:

  1. 上述观察结果基于在MongoDB 服务器 4.0 版上运行的查询(据我所知,也适用于3.6 版)。
  2. 解释方法 用于查找更新db.collection.explain().find( ... )和 。 db.collection.explain().update( ... )
  3. 请注意,您不能使用for 方法生成查询计划;它仅适用于和 方法。您可以使用mongo shell中的命令获取可以生成查询计划的方法列表: 。explain()updateOnefindAndModify()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"))
);

推荐阅读