В MongoDB db.collection.findAndModify()
метод променя и връща единичен документ.
collection
part е името на колекцията, с която да се извърши операцията.
Пример
Да предположим, че имаме колекция, наречена pets
който съдържа следните документи:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Можем да използваме db.collection.findAndModify()
метод за промяна на един от тези документи.
db.pets.findAndModify({
query: { type: "Dog" },
update: { type: "Cow" }
})
Резултат:
{ "_id" : 1, "name" : "Wag", "type" : "Dog" }
По подразбиране той връща оригиналния документ (не модифицираната версия).
Имайте предвид, че само едно куче беше актуализирано, въпреки че в колекцията има две кучета.
Нека проверим колекцията.
db.pets.find()
Резултат:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Dog" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Виждаме, че първият документ вече съдържа крава вместо куче. Но също така можем да видим, че полето за име на документа е изчезнало.
Това е така, защото, когато подадете документ към update
аргумент, db.collection.findAndModify()
извършва подмяна.
Използване на оператор за актуализиране
Ако искаме да актуализираме поле, но да оставим останалата част от документа непокътната, ще трябва да включим съответния/ите израз/и на оператора за актуализиране в нашия документ.
С колекцията в текущото й състояние, нека изпълним още един findAndModify()
операция срещу него, но този път ще използваме $set
Оператор за актуализиране, за да зададете само полето, което искаме да променим.
db.pets.findAndModify({
query: { type: "Dog" },
update: { $set: { type: "Horse" } }
})
Резултат:
{ "_id" : 2, "name" : "Bark", "type" : "Dog" }
Този път останалото куче беше актуализирано.
Нека да разгледаме колекцията.
db.pets.find()
Резултат:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Meow", "type" : "Cat" }
Този път съответното поле беше актуализирано, а останалата част от документа остана непокътната.
Върнете модифицирания документ
По подразбиране оригиналният документ се връща, когато използвате db.collection.findAndModify()
.
Ако предпочитате вместо това да върнете модифицирания документ, използвайте new
параметър.
По подразбиране това е new: false
, което води до връщане на оригиналния документ. Но посочва new: true
вместо това се връща модифицираният документ.
Нека направим още една модификация, но този път ще използваме new: true
.
db.pets.findAndModify({
query: { name: "Meow" },
update: { $set: { name: "Scratch" } },
new: true
})
Резултат:
{ "_id" : 3, "name" : "Scratch", "type" : "Cat" }
Затова преименувахме Meow
към Scratch
и изходът отразява нашите промени.
Нагоре
Можете да извършвате upserts, като посочите upsert: true
.
Upsert е опция, която можете да използвате при операции за актуализиране. Ако посоченият документ не съществува, се добавя нов. Ако го прави съществува, тогава оригиналният документ се актуализира (и не е вмъкнат документ).
Пример за използване на upsert: false
Ето пример за опит за актуализиране на несъществуващ документ, когато upsert: false
.
db.pets.findAndModify({
query: { _id: 4 },
update: { _id: 4, name: "Fetch", type: "Dog" },
new: true
})
Резултат:
null
Документът не съществуваше в колекцията и така findAndModify()
върна null
. Въпреки че не посочихме upsert: false
, знаем, че е невярно, защото това е стойността по подразбиране (т.е. това е стойността, която се използва, когато не посочите опция upsert).
Ако хвърлим още един поглед в колекцията, ще видим, че документът не е бил внесен.
db.pets.find()
Резултат:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Scratch", "type" : "Cat" }
Пример за използване на upsert: true
Ето го отново, но този път указваме upsert: true
.
db.pets.findAndModify({
query: { _id: 4 },
update: { _id: 4, name: "Fetch", type: "Dog" },
new: true,
upsert: true
})
Резултат:
{ "_id" : 4, "name" : "Fetch", "type" : "Dog" }
Този път се въвежда нов документ и ние виждаме въведения документ като изход (защото сме посочили new: true
).
Нека проверим колекцията отново.
db.pets.find()
Резултат:
{ "_id" : 1, "type" : "Cow" } { "_id" : 2, "name" : "Bark", "type" : "Horse" } { "_id" : 3, "name" : "Scratch", "type" : "Cat" } { "_id" : 4, "name" : "Fetch", "type" : "Dog" }
Така че можем да видим, че новият документ всъщност е бил въведен.
Параметърът arrayFilters
Когато работите с масиви, можете да използвате arrayFilters
параметър заедно с позиционния $
оператор, за да определи кои елементи на масива да актуализира. Това ви позволява да актуализирате елемент на масив въз основа на неговата стойност, дори ако не знаете неговата позиция.
Например, да предположим, че имаме колекция, наречена players
със следните документи:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 15, 11, 8 ] }
Бихме могли да изпълним следната заявка, за да актуализираме само онези елементи на масива, които имат стойност, по-висока от определено количество (в този случай 10).
db.players.findAndModify({
query: { scores: { $gte: 10 } },
update: { $set: { "scores.$[e]" : 10 } },
arrayFilters: [ { "e": { $gte: 10 } } ]
})
Резултат:
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
Както се очаква, това актуализира само един документ, въпреки че два документа отговарят на критериите.
Ето как изглеждат документите сега.
db.players.find()
Резултат:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 10, 10 ] } { "_id" : 3, "scores" : [ 15, 11, 8 ] }
В документ 2 бяха актуализирани два елемента на масива, тъй като тези елементи отговаряха на критериите.
Повече информация
db.collection.findAndModify()
Методът приема и други параметри, като writeConcern
, collection
, bypassDocumentValidation
и още.
Вижте документацията на MongoDB за db.collections.findAndModify()
за повече информация.