MongoDB има $push оператор и $addToSet оператор, като и двата правят много подобно нещо.
И двата оператора добавят стойности към съществуващ масив. Основната разлика е в начина, по който се справят с масиви, които вече съдържат стойността, която се опитвате да добавите, както и в модификаторите, които могат да се използват.
Разликите
| Съществуващи стойности | Ако стойността вече съществува в масива, $push ще продължи да добавя стойността (което води до дублиране на стойности). Въпреки това, $addToSet добавя стойността само ако тя вече не съществува в масива. Следователно, ако стойността вече съществува, $addToSet няма да го добави (няма да направи нищо). |
| Модификатори | $push Операторът може да се използва с допълнителни модификатори, като $sort , $slice и $position , докато $addToSet не може (поне не от MongoDB 4.4). |
Съществуващи стойности
Да предположим, че имаме колекция със следните документи:
db.players.find() Резултат:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 5 ] }
Нека използваме $addToSet за да опитате да добавите стойност към един от масивите.
db.players.update(
{ _id: 3 },
{ $addToSet: { scores: 5 } }
) Изход:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
Това ни казва, че е имало съответстващ документ (документ 3), но той не е променен. Не беше променено, защото стойността, която се опитахме да вмъкнем (5 ) вече съществува в масива.
Нека погледнем в колекцията:
db.players.find() Резултат:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 5 ] } Както се очакваше, документ 3 не е променен.
Нека опитаме $push вместо това:
db.players.update(
{ _id: 3 },
{ $push: { scores: 5 } }
) Изход:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) Този път виждаме, че документът е променен.
Можем да потвърдим това, като проверим колекцията отново:
db.products.find() Резултат:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 5, 5 ] } Модификатори
$push операторът може да се използва с модификатори като $position , $sort и $slice .
$addToSet операторът не може да се използва с тези модификатори.
Ето какво се случва, ако се опитам да използвам тези модификатори с $addToSet :
db.players.update(
{ _id: 3 },
{
$addToSet: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
) Изход:
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 2,
"errmsg" : "Found unexpected fields after $each in $addToSet: { $each: [ 12.0 ], $position: 0.0, $sort: 1.0, $slice: 5.0 }"
}
})
Съобщението за грешка ни казва, че $position , $sort и $slice са неочаквани полета (т.е. не трябва да са там).
Нека опитаме същите модификатори с $push :
db.players.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
) Изход:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) Този път работи без грешка.
Проверете резултата:
db.players.find() Резултат:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] }
{ "_id" : 2, "scores" : [ 8, 17, 18 ] }
{ "_id" : 3, "scores" : [ 3, 5, 5, 5, 12 ] }
Можем да видим, че стойността е добавена. Въпреки че посочихме $position: 0 , ние също така посочихме $sort: 1 , което означава, че масивът е сортиран, след като сме го позиционирали.
Също така посочихме $slice: 5 , което ограничава масива до само 5 елемента (което така или иначе се оказа точно колко елемента има в масива).