db.collection.findAndModify()

在本页面

Definition

findAndModify()方法具有以下形式:

在版本 3.6 中更改。

db.collection.findAndModify({
    query: <document>,
    sort: <document>,
    remove: <boolean>,
    update: <document>,
    new: <boolean>,
    fields: <document>,
    upsert: <boolean>,
    bypassDocumentValidation: <boolean>,
    writeConcern: <document>,
    collation: <document>,
    arrayFilters: [ <filterdocument1>, ... ]
});

db.collection.findAndModify()方法采用带有以下嵌入式文档字段的文档参数:

Parameter Type Description
query document 可选的。修改的选择标准。 query字段采用的是与db.collection.find()方法中相同的query selectors。尽管查询可能匹配多个文档,但findAndModify() 将仅选择一个文档进行修改


如果未指定,则默认为空文档。
从 MongoDB 3.6.14(和 3.4.23)开始,如果查询参数不是文档,则操作错误。
| sort |文档|可选。确定如果查询选择多个文档,则操作将修改哪个文档。 findAndModify()以此参数指定的排序 Sequences 修改第一个文档。
从 MongoDB 3.6.14(和 3.4.23)开始,如果 sort 参数不是文档,则操作错误。
| remove |布尔值|必须指定removeupdate字段。删除在query字段中指定的文档。将此设置为true以删除所选的文档。默认值为false
| update | document |必须指定removeupdate字段。执行所选文档的更新。 update字段采用相同的update operatorsfield: value规范来修改所选文档。
| new |布尔值|可选。 true时,返回修改后的文档而不是原始文档。 findAndModify()方法忽略remove操作的new选项。默认值为false
| fields |文档|可选。要返回的字段子集。 fields文档指定包含1的字段,如fields: { <field1>: 1, <field2>: 1, ... }。参见projection
从 MongoDB 3.6.14(和 3.4.23)开始,如果 fields 参数不是文档,则操作错误。
| upsert |布尔值|可选。与update字段结合使用。
truefindAndModify()时:
如果没有文档与query相匹配,则创建一个新文档。有关更多详细信息,请参见upsert behavior
更新与query匹配的单个文档。
为避免多次更新,请确保query字段为uniquely indexed
默认为false
| bypassDocumentValidation |布尔值|可选。使db.collection.findAndModify在操作过程中绕过文档验证。这使您可以更新不满足验证要求的文档。
版本 3.2 中的新功能。
| writeConcern |文档|可选。表示write concern的文档。省略使用默认的写关注。
版本 3.2 中的新功能。
| maxTimeMS |整数|可选。指定用于处理操作的时间限制(以毫秒为单位)。
| collation |文档|可选。
指定用于操作的collation
Collation允许用户为字符串比较指定特定于语言的规则,例如字母大写和重音符号的规则。
排序规则选项具有以下语法:
collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}
指定排序规则时,locale字段为必填字段;所有其他排序规则字段都是可选的。有关字段的说明,请参见Collation Document
如果未指定排序规则,但是集合具有默认排序规则(请参见db.createCollection()),则该操作将使用为集合指定的排序规则。
如果没有为集合或操作指定排序规则,则 MongoDB 使用先前版本中使用的简单二进制比较进行字符串比较。
您不能为一个操作指定多个排序规则。例如,您不能为每个字段指定不同的排序规则,或者如果对排序执行查找,则不能对查找使用一种排序规则,而对排序使用另一种排序规则。
3.4 版中的新功能。
| arrayFilters | array |可选。筛选器文档数组,用于确定要对数组字段进行更新操作要修改的数组元素。
在更新文档中,使用$[<identifier>]过滤的位置运算符定义标识符,然后在数组过滤器文档中引用该标识符。如果更新文档中未包含标识符,则不能具有数组过滤器文档作为标识符。

Note





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



您可以在更新文档中多次包含相同的标识符;但是,对于更新文档中的每个唯一标识符($[identifier]),您必须指定**完全对应的数组过滤器文档。即,您不能为同一标识符指定多个数组过滤器文档。例如,如果更新语句包含标识符x(可能多次),则不能为arrayFilters指定以下内容,其中包括x的 2 个单独的过滤器文档:
[
{ "x.a": { $gt: 85 } },
{ "x.b": { $gt: 80 } }
br]
但是,您可以在单个过滤器文档中的同一标识符上指定复合条件,例如以下示例:
[
{ $or: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
[
{ $and: [{"x.a": {$gt: 85}}, {"x.b": {$gt: 80}}] }
]
[
{ "x.a": { $gt: 85 },“ x.b”:{ $gt: 80 }}
br]
有关示例,请参见为阵列更新操作指定 arrayFilters
3.6 版中的新功能。

Return Data

对于删除操作,如果查询与文档匹配,则findAndModify()返回删除的文档。如果查询与要删除的文档不匹配,则findAndModify()返回null

对于更新操作,findAndModify()返回以下值之一:

在版本 3.0 中进行了更改:在以前的版本中,如果要进行更新,则指定sort且指定upsert: true,并且未设置new选项或new: false,则db.collection.findAndModify()返回空文档{}而不是null

Behavior

Upsert 和唯一索引

findAndModify()包含upsert: true选项 并且 查询字段未唯一索引时,在某些情况下,该方法可以多次插入文档。

在以下示例中,不存在名称为Andy的文档,并且多个 Client 端发出以下命令:

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

然后,如果这些 Client 端的findAndModify()方法在任何命令开始modify阶段之前完成query阶段,并且name字段上没有唯一索引,则这些命令可能全部执行 upsert,从而创建多个重复文档。

为防止创建多个具有相同名称的重复文档,请在name字段上创建一个unique index。有了此唯一索引,多种方法将表现出以下行为之一:

Sharded Collections

sharded环境中使用findAndModify时,针对* sharded *集合的分片群集,query 必须 包含shard key

针对非分片集合的针对mongos实例发出的findAndModify操作正常运行。

Document Validation

db.collection.findAndModify()方法增加了对bypassDocumentValidation选项的支持,该选项使您可以在具有验证规则的集合中插入或更新文档时绕过document validation

与更新方法的比较

更新文档时,findAndModify()update()方法的操作不同:

使用update()方法的默认行为,您无法指定多个文档匹配时要更新的单个文档。

update()方法返回包含操作状态的WriteResult对象。要返回更新的文档,请使用find()方法。但是,其他更新可能已在您的更新和文档检索之间修改了文档。同样,如果更新仅修改了一个文档,但匹配了多个文档,则您将需要使用其他逻辑来标识更新的文档。

修改单个文档时,findAndModify()update()方法都从原子上*更新该文档。有关这些方法的交互作用和操作 Sequences 的更多详细信息,请参见原子性和 Transaction

Examples

更新并返回

以下方法更新并返回人员集合中与查询条件相匹配的现有文档:

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

此方法执行以下操作:

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

要返回修改后的文档,请将new:true选项添加到方法中。

如果没有文档符合query条件,则该方法返回null

Upsert

以下方法包括update操作的upsert: true选项,以更新匹配的文档,或者如果不存在匹配的文档,则创建新文档:

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

如果该方法找到匹配的文档,则该方法将执行更新。

如果该方法没有找到匹配的文档,则该方法将创建一个新文档。因为该方法包括sort选项,所以它返回一个空文档{ }作为原始(预修改)文档:

{ }

如果该方法不包含sort选项,则该方法返回null

null

返回新文件

以下方法同时包含upsert: true选项和new:true选项。该方法更新匹配的文档并返回更新的文档,或者,如果不存在匹配的文档,则插入文档并在value字段中返回新插入的文档。

在下面的示例中,people集合中没有任何文档与query条件匹配:

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

该方法返回新插入的文档:

{
   "_id" : ObjectId("50f49ad6444c11ac2448a5d6"),
   "name" : "Pascal",
   "rating" : 25,
   "score" : 1,
   "state" : "active"
}

排序并删除

通过在rating字段中包含sort规范,以下示例从people集合中删除state值为active且匹配文件中最低rating的单个文档:

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

该方法返回已删除的文档:

{
   "_id" : ObjectId("52fba867ab5fdca1299674ad"),
   "name" : "XYZ123",
   "score" : 1,
   "state" : "active",
   "rating" : 3
}

Specify Collation

3.4 版的新功能。

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

集合myColl具有以下文档:

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

以下操作包括collation选项:

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

该操作返回以下文档:

{ "_id" : 1, "category" : "café", "status" : "A" }

为阵列更新操作指定 arrayFilters

3.6 版的新功能。

从 MongoDB 3.6 开始,在更新数组字段时,您可以指定arrayFilters来确定要更新的数组元素。

更新元素匹配 arrayFilters 条件

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

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

要修改grades数组中所有大于或等于100的元素,请在db.collection.findAndModify方法中将过滤后的位置运算符$[<identifier>]arrayFilters选项一起使用:

db.students.findAndModify({
   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 ] }

更新一系列文档的特定元素

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

db.students2.insert([
   {
      "_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 }
      ]
   }
])

要为grades数组中坡度大于或等于85的所有元素修改mean字段的值,请在db.collection.findAndModify方法中将过滤后的位置运算符$[<identifier>]arrayFilters一起使用:

db.students2.findAndModify({
   query: { },
   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 }
   ]
}
首页