文档菜单
文档首页
/
MongoDB 手册
/ / /

findAndModify

本页内容

  • 定义
  • 兼容性
  • 语法
  • 命令字段
  • 输出
  • 行为
  • 示例
findAndModify

findAndModify 命令更新并返回单个文档。默认情况下,返回的文档不包含所做的更新修改。要返回包含所做的更新修改的文档,请使用 new 选项。

提示

mongosh 中,此命令也可以通过db.collection.findAndModify() 辅助方法.

辅助方法对 mongosh 用户来说很方便,但它们可能不会返回与数据库命令相同级别的信息。在不需要方便或需要额外的返回字段的情况下,请使用数据库命令。

此命令在以下环境中托管的服务器可用

  • MongoDB Atlas:云中 MongoDB 部署的完全托管服务

注意

此命令在所有 MongoDB Atlas 集群中都受支持。有关 Atlas 对所有命令的支持信息,请参阅 不受支持的命令。

已更改版本5.0.

该命令具有以下语法

db.runCommand(
{
findAndModify: <collection-name>,
query: <document>,
sort: <document>,
remove: <boolean>,
update: <document or aggregation pipeline>,
new: <boolean>,
fields: <document>,
upsert: <boolean>,
bypassDocumentValidation: <boolean>,
writeConcern: <document>,
maxTimeMS: <integer>,
collation: <document>,
arrayFilters: <array>,
hint: <document|string>,
comment: <any>,
let: <document> // Added in MongoDB 5.0
}
)

该命令包含以下字段

字段
类型
描述
query
文档

可选。修改的选择标准。该query字段使用与查询选择器相同的查询,用于db.collection.find()方法。虽然查询可以匹配多个文档,但findAndModify 将仅选择一个文档进行更新

如果未指定,则默认为空文档。

如果查询参数不是文档,则操作错误。

sort

文档

可选。确定如果查询选择多个文档,则操作更新的文档。 findAndModify根据此参数指定的排序顺序更新第一个文档。

如果排序参数不是文档,则操作错误。

MongoDB不会按特定顺序存储集合中的文档。当对一个包含重复值的字段进行排序时,包含这些值的文档可能以任何顺序返回。

如果需要一致的排序顺序,请在排序中包含至少一个包含唯一值的字段。最简单的方法是在排序查询中包含 _id 字段。

有关更多信息,请参阅 排序一致性

删除
布尔值
必须指定 removeupdate 字段。删除 query 字段中指定的文档。将其设置为 true 以删除选定的文档。默认为 false
更新
文档或数组

必须指定 removeupdate 字段。对选定的文档执行更新。

  • 如果传递了一个包含 更新运算符表达式 的文档,则 findAndModify 执行指定的修改。

  • 如果传递了一个替换文档 { <field1>: <value1>, ...},则 findAndModify 执行替换。

  • 如果传递了一个 聚合管道 [ <stage1>, <stage2>, ... ],则 findAndModify 根据管道更新文档。管道可以包含以下阶段

布尔值
可选。当设置为 true 时,返回更新后的文档而不是原始文档。默认为 false
字段
文档

可选。要返回的字段子集。该 fields 文档指定使用 1 包含字段,例如:fields: { <field1>: 1, <field2>: 1, ... }。有关投影的信息,请参阅 投影。

如果字段参数不是一个文档,则操作会出错。

upsert
布尔值

可选。与 update 字段一起使用。

当设置为 true 时,findAndModify

  • 如果没有文档与 query 匹配,则创建一个新的文档。有关详细信息,请参阅 upsert 行为。

  • 更新与 query 匹配的单个文档。

为了避免多个 upsert,请确保 query 字段是 唯一索引 的。有关示例,请参阅 具有唯一索引的 upsert

默认为 false,当没有找到匹配项时不会插入新的文档。

bypassDocumentValidation
布尔值
可选。启用findAndModify在操作期间绕过文档验证。这允许您更新不符合验证要求的文档。
writeConcern
文档

可选。表示写关注的文档。省略则使用默认写关注。

在事务中运行操作时,不要显式设置写关注。要使用事务与写关注,请参阅事务和写关注。

maxTimeMS
非负整数

可选。

指定一个以毫秒为单位的时间限制。如果您未指定maxTimeMS的值,操作将不会超时。显式指定值为0表示默认的无界行为。

MongoDB使用与db.killOp()相同的机制终止超过其分配时间限制的操作。MongoDB仅在操作的一个指定的中断点处终止操作。

findAndModify
字符串
要运行命令的集合。
collation
文档

可选。

指定操作要使用的排序规则

排序规则允许用户指定字符串比较的语言特定规则,例如字母大小写和重音符号的规则。

排序规则的语法如下

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

指定排序规则时,locale字段是必填的;所有其他排序规则字段都是可选的。有关字段的说明,请参阅排序规则文档。

如果未指定排序规则,但集合具有默认排序规则(请参阅db.createCollection()),则操作将使用集合指定的排序规则。

如果为集合或操作未指定排序规则,MongoDB将使用先前版本中用于字符串比较的简单二进制比较。

您不能为操作指定多个排序规则。例如,您不能按字段指定不同的排序规则,或者在进行带有排序的查找时,您不能为查找和排序使用不同的排序规则。

arrayFilters
数组

可选。一个过滤器文档数组,用于确定更新操作中要修改的数组字段的哪些数组元素。

在更新文档中,使用$[<identifier>]位置过滤器运算符来定义一个标识符,然后在数组过滤器文档中引用它。如果标识符未包含在更新文档中,则不能为标识符有一个数组过滤器文档。

<identifier>必须以下划线开头,并且只能包含字母数字字符。

在更新文档中,您可以多次包含相同的标识符;然而,对于更新文档中每个不同的标识符($[标识符]),您必须指定一个对应的数组过滤器文档。也就是说,您不能为同一个标识符指定多个数组过滤器文档。例如,如果更新语句包括标识符 x(可能多次),您不能为包含 2 个独立过滤器文档的 arrayFilters 指定以下内容

// INVALID
[
{ "x.a": { $gt: 85 } },
{ "x.b": { $gt: 80 } }
]

但是,您可以在单个过滤器文档中指定同一标识符的复合条件,如下面的示例所示

// Example 1
[
{ $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 2
[
{ $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
// Example 3
[
{ "x.a": { $gt: 85 }, "x.b": { $gt: 80 } }
]

有关示例,请参阅使用 arrayFilters 的数组更新操作。

arrayFilters 不可用于使用聚合管道的更新操作。

提示
文档或字符串

可选。一个文档或字符串,用于指定用于支持 查询 的索引。

该选项可以是一个索引规范文档或索引名称字符串。

如果您指定了一个不存在的索引,则操作会出错。

有关示例,请参阅findAndModify 操作指定 hint

注释
任何内容

可选。用户提供的注释,用于附加到该命令。一旦设置,此注释将出现在以下位置的该命令记录旁边

注释可以是任何有效的 BSON 类型(字符串、整数、对象、数组等)。

文档

可选。

指定一个包含变量列表的文档。这允许您通过将变量与查询文本分开来提高命令的可读性。

文档语法是

{
<variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n>
}

变量设置为表达式返回的值,之后不能更改。

要在命令中访问变量的值,请使用双美元符号前缀($$)以及变量名,形式为 $$<变量名>。例如:$$targetTotal

要使用变量来过滤结果,您必须在 $expr 操作符中访问变量。

有关使用 let 和变量的完整示例,请参阅let 中使用变量。

版本5.0.

命令 findAndModify 返回具有以下字段的文档

字段
类型
描述
value
文档
包含命令返回的值。有关详细信息,请参阅 value
lastErrorObject
文档
包含有关更新文档的信息。有关详细信息,请参阅 lastErrorObject
ok
number
包含命令的执行状态。成功时为 1,如果发生错误则为 0

嵌入的 lastErrorObject 文档包含以下字段

字段
类型
描述
n
整数
包含匹配更新谓词的文档数量或插入或删除的文档数量。
updatedExisting
布尔值

包含 true 如果执行了 update 操作

  • 更新了现有文档。

  • 找到了文档,但它已经处于所需的最终状态,因此实际上没有发生更新。

upserted
文档
包含在具有 upsert: trueupdate 操作导致新文档的情况下插入的文档的 ObjectId

对于 删除 操作,如果查询匹配到文档,则 包含被删除的文档。如果查询没有匹配到要删除的文档,则 包含 null

对于 更新 操作,内嵌的 文档包含以下内容

  • 如果未设置 new 参数或其值为 false

    • 如果查询匹配到文档,则包含预修改的文档;

    • 否则,包含 null

  • 如果 new 的值为 true

    • 如果查询返回匹配,则包含更新的文档;

    • 如果 upsert: true 且没有文档与查询匹配,则包含插入的文档;

    • 否则,包含 null

除非存在一个唯一索引来防止重复,否则Upsert可能会创建重复的文档。

考虑一个例子,没有名为Andy的文档存在,并且多个客户端几乎同时发出以下命令

db.runCommand(
{
findAndModify: "people",
query: { name: "Andy" },
update: { $inc: { score: 1 } },
upsert: true
}
)

如果所有findAndModify操作在任何客户端成功插入数据之前完成查询阶段,并且name字段上没有唯一索引,则每个findAndModify操作可能会导致插入,创建多个name: Andy的文档。

name字段的唯一索引确保只能创建一个文档。有了唯一索引,现在多个findAndModify操作表现出以下行为

  • 只有一个findAndModify操作将成功插入一个新文档。

  • 其他findAndModify操作要么更新新插入的文档,要么由于唯一键冲突而失败。

    为了使其他findAndModify操作能够更新新插入的文档,以下所有条件都必须满足

    • 目标集合有一个会导致重复键错误的唯一索引。

    • 更新操作不是updateMany,或者multi设置为false

    • 更新匹配条件是

      • 一个单个相等谓词。例如{ "fieldA" : "valueA" }

      • 相等谓词的逻辑AND。例如{ "fieldA" : "valueA", "fieldB" : "valueB" }

    • 相等谓词中的字段与唯一索引键模式中的字段匹配。

    • 更新操作不修改唯一索引键模式中的任何字段。

以下表格显示了在键冲突发生时,要么更新要么失败的upsert操作的示例。

唯一索引键模式
更新操作
结果
{ name : 1 }
db.people.updateOne(
{ name: "Andy" },
{ $inc: { score: 1 } },
{ upsert: true }
)
匹配文档的score字段增加1。
{ name : 1 }
db.people.updateOne(
{ name: { $ne: "Joe" } },
{ $set: { name: "Andy" } },
{ upsert: true }
)
操作失败,因为它修改了唯一索引键模式中的字段(name)。
{ name : 1 }
db.people.updateOne(
{ name: "Andy", email: "andy@xyz.com" },
{ $set: { active: false } },
{ upsert: true }
)
操作失败,因为等价谓词字段(nameemail)与索引键字段(name)不匹配。

要在分片集合上使用 findAndModify

  • 如果您只针对一个分片,您可以在 query 字段中使用部分分片键,或者

  • 您可以在 query 字段中提供一个全部分片键的等价条件。

  • 从版本 7.1 开始,您不需要在查询规范中提供 分片键_id 字段。

分片集合中的文档可能缺少分片键字段。为了针对缺少分片键的文档,您可以使用 null 等价匹配另一个过滤条件(例如 _id 字段)结合使用。例如

{ _id: <value>, <shardkeyfield>: null } // _id of the document missing shard key

除非分片键字段是不可变的 _id 字段,否则您可以更新文档的分片键值。

注意

分片集合中的文档可能缺少分片键字段。在更改文档的分片键值时,请谨慎操作,以避免意外删除分片键。

要使用 findAndModify:

  • 您必须在 mongos 上运行。不要直接在分片上执行操作。

  • 您必须在 事务 中运行,或作为一个 可重试的写入操作。

  • 您必须在完整的分片键上包含一个相等过滤器。

分片集合中的文档可能 缺少分片键字段。要使用 findAndModify 来设置文档的 缺失 分片键

  • 您必须在 mongos 上运行。不要直接在分片上执行操作。

  • 如果新的分片键值不是 null,您必须在 事务 中运行,或作为一个 可重试的写入操作。

  • 您必须在完整的分片键上包含一个相等过滤器。

提示

由于缺失的键值作为 null 相等匹配的一部分返回,为了避免更新具有 null 值的键,根据需要包含其他查询条件(例如,在 _id 字段上)。

另请参阅

findAndModify 命令增加了对 bypassDocumentValidation 选项的支持,允许在具有验证规则的集合中插入或更新文档时跳过 文档验证

在更新文档时,findAndModifyupdateOne() 方法的工作方式不同

  • 如果多个文档匹配更新条件,对于 findAndModify,您可以指定一个 sort 以提供对要更新哪个文档的控制

    updateOne() 更新第一个匹配的文档

  • 默认情况下,findAndModify 返回一个包含文档修改前版本以及操作状态的对象. 要获取更新后的文档,使用 new 选项

    updateOne() 方法返回一个 WriteResult() 对象,其中包含操作状态

    要返回更新后的文档,使用 find() 方法。但是,其他更新可能在您的更新和文档检索之间修改了文档。此外,如果更新仅修改了一个文档但多个文档匹配,您需要使用额外的逻辑来识别更新的文档

当修改 单个 文档时,findAndModifyupdateOne() 方法 原子性地 更新文档。有关这些方法的交互和操作顺序的更多详细信息,请参阅 原子性和事务

提示

另请参阅

findAndModify可以在分布式事务中使用。

重要

在大多数情况下,分布式事务比单文档写入产生的性能成本更高,分布式事务的可用性不应替代有效的架构设计。在许多场景中,非规范化数据模型(嵌入文档和数组)将仍然是最适合您数据和用例的。也就是说,在许多场景中,适当地建模数据将最大限度地减少分布式事务的需求。

有关其他交易使用考虑事项(如运行时限制和oplog大小限制),请参阅生产注意事项

如果事务不是跨分片写入事务,则可以在分布式事务中创建集合和索引。

带有upsert: truefindAndModify可以在现有集合或不存在集合上运行。如果在不存在的集合上运行,则该操作将创建该集合。

在事务中运行操作时,不要显式设置写关注。要使用事务与写关注,请参阅事务和写关注。

以下命令更新了 people 集合中与 query 条件匹配的现有文档

db.runCommand(
{
findAndModify: "people",
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
}
)

此命令执行以下操作

  1. querypeople 集合中找到一个文档,其中 name 字段值为 Tomstate 字段值为 active,并且 rating 字段值大于 10。

  2. 排序操作符sort将查询结果按升序排列。如果多个文档满足query条件,则按此sort顺序选择第一个文档进行修改。

  3. 更新操作符update通过链接incrementsscore字段的值增加1。

  4. 该命令返回一个包含以下字段的文档

    • lastErrorObject字段包含命令的详细信息,包括字段updatedExisting,其值为true,以及

    • value字段包含为此更新选择的原始(即修改前)文档

      {
      "lastErrorObject" : {
      "connectionId" : 1,
      "updatedExisting" : true,
      "n" : 1,
      "syncMillis" : 0,
      "writtenTo" : null,
      "err" : null,
      "ok" : 1
      },
      value" : {
      "_id" : ObjectId("54f62d2885e4be1f982b9c9c"),
      "name" : "Tom",
      "state" : "active",
      "rating" : 100,
      "score" : 5
      },
      "ok" : 1
      }

要将更新后的文档返回到value字段,请将new:true选项添加到命令中。

如果没有文档匹配query条件,则命令返回一个包含nullvalue字段的文档

{ "value" : null, "ok" : 1 }

mongosh和许多驱动程序提供findAndModify()辅助方法。使用shell辅助方法,此先前操作可以采用以下形式

db.people.findAndModify( {
query: { name: "Tom", state: "active", rating: { $gt: 10 } },
sort: { rating: 1 },
update: { $inc: { score: 1 } }
} );

但是,findAndModify()shell辅助方法仅返回未修改的文档,或者如果newtrue,则返回更新后的文档。

{
"_id" : ObjectId("54f62d2885e4be1f982b9c9c"),
"name" : "Tom",
"state" : "active",
"rating" : 100,
"score" : 5
}

以下findAndModify命令包含用于更新操作的upsert: true选项,以更新匹配的文档,或者在没有匹配的文档存在时创建新文档

db.runCommand(
{
findAndModify: "people",
query: { name: "Gus", state: "active", rating: 100 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true
}
)

如果命令找到一个匹配的文档,则执行更新。

如果命令没有找到匹配的文档,则具有upsert: trueupdate操作将导致插入,并返回一个包含以下字段的文档

  • lastErrorObject字段包含命令的详细信息,包括包含新插入文档的_id值的字段upserted,以及

  • 包含nullvalue字段。

{
"value" : null,
"lastErrorObject" : {
"updatedExisting" : false,
"n" : 1,
"upserted" : ObjectId("54f62c8bc85d4472eadea26f")
},
"ok" : 1
}

以下findAndModify命令包含upsert: true选项和new:true选项。该命令要么更新匹配的文档并返回更新后的文档,要么如果没有匹配的文档存在,则在value字段中插入文档并返回新插入的文档。

在以下示例中,people集合中没有文档与query条件匹配

db.runCommand(
{
findAndModify: "people",
query: { name: "Pascal", state: "active", rating: 25 },
sort: { rating: 1 },
update: { $inc: { score: 1 } },
upsert: true,
new: true
}
)

该命令在value字段中返回新插入的文档

{
"lastErrorObject" : {
"connectionId" : 1,
"updatedExisting" : false,
"upserted" : ObjectId("54f62bbfc85d4472eadea26d"),
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
"value" : {
"_id" : ObjectId("54f62bbfc85d4472eadea26d"),
"name" : "Pascal",
"rating" : 25,
"state" : "active",
"score" : 1
},
"ok" : 1
}

通过在rating字段上包含一个sort规范,以下示例从people集合中删除一个具有state值为active和最低rating的匹配文档

db.runCommand(
{
findAndModify: "people",
query: { state: "active" },
sort: { rating: 1 },
remove: true
}
)

该命令返回被删除的文档

{
"lastErrorObject" : {
"connectionId" : 1,
"n" : 1,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1
},
"value" : {
"_id" : ObjectId("54f62a6785e4be1f982b9c9b"),
"name" : "XYZ123",
"score" : 1,
"state" : "active",
"rating" : 3
},
"ok" : 1
}

排序规则允许用户指定字符串比较的语言特定规则,例如字母大小写和重音符号的规则。

集合myColl包含以下文档

{ _id: 1, category: "café", status: "A" }
{ _id: 2, category: "cafe", status: "a" }
{ _id: 3, category: "cafE", status: "a" }

以下操作包括校对选项

db.runCommand(
{
findAndModify: "myColl",
query: { category: "cafe", status: "a" },
sort: { category: 1 },
update: { $set: { status: "Updated" } },
collation: { locale: "fr", strength: 1 }
}
)

操作返回以下文档

{
"lastErrorObject" : {
"updatedExisting" : true,
"n" : 1
},
"value" : {
"_id" : 1,
"category" : "café",
"status" : "A"
},
"ok" : 1
}

注意

arrayFilters 不可用于使用聚合管道的更新操作。

当更新数组字段时,可以指定 arrayFilters 以确定要更新的数组元素。

注意

arrayFilters 不可用于使用聚合管道的更新操作。

创建一个包含以下文档的集合 students

db.students.insertMany( [
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
] )

要更新 grades 数组中所有大于或等于 100 的元素,使用带 arrayFilters 选项的位置 $[<identifier>] 操作符

db.runCommand(
{
findAndModify: "students",
query: { grades: { $gte: 100 } },
update: { $set: { "grades.$[element]" : 100 } },
arrayFilters: [ { "element": { $gte: 100 } } ]
}
)

该操作更新单个文档的 grades 字段,操作后,集合包含以下文档

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }

注意

arrayFilters 不可用于使用聚合管道的更新操作。

创建一个包含以下文档的集合 students2

db.students2.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
] )

以下操作找到文档,其中 _id 字段等于 1,并使用带过滤位置操作符的聚合管道 $[<identifier>]arrayFilters,以更新 grades 数组中所有成绩大于或等于 85mean

db.runCommand(
{
findAndModify: "students2",
query: { _id : 1 },
update: { $set: { "grades.$[elem].mean" : 100 } },
arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
}
)

该操作更新单个文档的 grades 字段,操作后,集合包含以下文档

{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}

findAndModify 可以接受用于更新的聚合管道。该管道可以由以下阶段组成

使用聚合管道允许使用更具有表达性的更新语句,例如根据当前字段值表达条件更新或使用另一个字段(们)的值更新一个字段。

例如,创建一个包含以下文档的集合 students2

db.students2.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
] )

以下操作找到文档,其中 _id 字段等于 1,并使用聚合管道从 grades 字段计算新的字段 total

db.runCommand(
{
findAndModify: "students2",
query: { "_id" : 1 },
update: [ { $set: { "total" : { $sum: "$grades.grade" } } } ],
new: true
}
)

注意

管道中使用的 $set 指的是聚合阶段的 $set 而不是更新操作符 $set

操作完成后,集合包含以下文档

{
"_id" : 1,
"grades" : [ { "grade" : 80, "mean" : 75, "std" : 6 }, { "grade" : 85, "mean" : 90, "std" : 4 }, { "grade" : 85, "mean" :85, "std" : 6 } ],
"total" : 250
}
{
"_id" : 2,
"grades" : [ { "grade" : 90, "mean" : 75, "std" : 6 }, { "grade" : 87, "mean" : 90, "std" : 3 }, { "grade" : 85, "mean" : 85,"std" : 4 } ]
}

mongosh 中,创建一个包含以下文档的 members 集合

db.members.insertMany( [
{ "_id" : 1, "member" : "abc123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 2, "member" : "xyz123", "status" : "A", "points" : 60, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" },
{ "_id" : 3, "member" : "lmn123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 4, "member" : "pqr123", "status" : "D", "points" : 20, "misc1" : "Deactivated", "misc2" : null },
{ "_id" : 5, "member" : "ijk123", "status" : "P", "points" : 0, "misc1" : null, "misc2" : null },
{ "_id" : 6, "member" : "cde123", "status" : "A", "points" : 86, "misc1" : "reminder: ping me at 100pts", "misc2" : "Some random comment" }
] )

在集合上创建以下索引

db.members.createIndex( { status: 1 } )
db.members.createIndex( { points: 1 } )

以下操作显式提示使用索引 { status: 1 }

db.runCommand({
findAndModify: "members",
query: { "points": { $lte: 20 }, "status": "P" },
remove: true,
hint: { status: 1 }
})

注意

如果您指定了一个不存在的索引,则操作会出错。

要查看使用的索引,请在操作上运行 explain

db.runCommand(
{
explain: {
findAndModify: "members",
query: { "points": { $lte: 20 }, "status": "P" },
remove: true,
hint: { status: 1 }
},
verbosity: "queryPlanner"
}
)

版本5.0.

要定义可以在命令的其他部分访问的变量,请使用 let 选项。

注意

要使用变量过滤结果,必须在 $expr 操作符中访问该变量。

创建一个名为 cakeFlavors 的集合

db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )

以下示例在 let 中定义了一个 targetFlavor 变量,并使用该变量将蛋糕口味从樱桃更改为橙子

db.cakeFlavors.runCommand( {
findAndModify: db.cakeFlavors.getName(),
query: { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } },
update: { flavor: "orange" },
let: { targetFlavor: "cherry" }
} )

返回

查找