Всъщност да направите това, което изглежда, сякаш казвате, че правите, не е единствена операция, но ще разгледам частите, необходими, за да направя това или по друг начин да обхвана други възможни ситуации.
Това, което търсите, е отчасти позиционния $
оператор. Имате нужда от част от вашата заявка, за да "намерите" и елемента от масива, който искате.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$.vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Така че $
означава съвпадащата позиция в масива, така че частта за актуализиране да знае кой елемент в масива да актуализира. Можете да получите достъп до отделни полета на документа в масива или просто да посочите целия документ за актуализиране на тази позиция.
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Ако полетата всъщност не се променят и просто искате да вмъкнете нов елемент от масива, ако същият не съществува, тогава можете да използвате $addToSet
db.products.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
$addToSet:{
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
)
Ако обаче просто търсите "натискане" към масив от единствена ключова стойност, ако тя не съществува, тогава трябва да направите още малко ръчна обработка, като първо видите дали елементът в масива съществува и след това направите $push
изявление, когато не е така.
Получавате помощ от методите на mongoose за това, като проследявате броя на документите, засегнати от актуализацията:
Product.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095"),
"recentviews.viewedby": "abc"
},
{
"$set": {
"recentviews.$": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
},
function(err,numAffected) {
if (numAffected == 0) {
// Document not updated so you can push onto the array
Product.update(
{
"_id": ObjectId("536c55bf9c8fb24c21000095")
},
{
"$push": {
"recentviews": {
"viewedby": "abc",
"vieweddate": ISODate("2014-05-09T04:12:47.907Z")
}
}
},
function(err,numAffected) {
}
);
}
}
);
Единствената дума за предупреждение тук е, че има малка промяна в реализацията в съобщенията writeConcern от MongoDB 2.6 към по-ранни версии. В момента не сте сигурни как API на mongoose всъщност изпълнява връщането на numAffected
аргумент в обратното извикване разликата може да означава нещо.
В предишни версии, дори ако данните, които сте изпратили в първоначалната актуализация, съвпадат точно със съществуващ елемент и не е била необходима реална промяна, тогава „променената“ сума ще бъде върната като 1
въпреки че всъщност нищо не е актуализирано.
От MongoDB 2.6 отговорът за притеснение при запис съдържа две части. Едната част показва модифицирания документ, а другата показва съвпадението. Така че докато съвпадението ще бъде върнато от частта на заявката, съответстваща на съществуващ елемент, действителният брой на модифицираните документи ще се върне като 0
ако всъщност не е била необходима промяна.
Така че в зависимост от това как действително е внедрен номерът за връщане в mongoose, всъщност може да е по-безопасно да използвате $addToSet
оператор на тази вътрешна актуализация, за да се уверите, че ако причината за нулевите засегнати документи не е просто, че точният елемент вече съществува.