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 елемента (което така или иначе се оказа точно колко елемента има в масива).