MongoDB có $push
toán tử và một $addToSet
toán tử, cả hai đều làm một điều rất giống nhau.
Cả hai toán tử đều nối các giá trị vào một mảng hiện có. Sự khác biệt chính là ở cách chúng xử lý các mảng đã chứa giá trị mà bạn đang cố gắng nối thêm và cả trong các công cụ sửa đổi có thể được sử dụng.
Sự khác biệt
Giá trị hiện tại | Nếu giá trị đã tồn tại trong mảng, hãy $push sẽ vẫn thêm giá trị (dẫn đến các giá trị trùng lặp). Tuy nhiên, $addToSet chỉ nối giá trị nếu nó chưa tồn tại trong mảng. Do đó, nếu giá trị đã tồn tại, $addToSet sẽ không nối nó (nó sẽ không làm gì cả). |
Công cụ sửa đổi | $push toán tử có thể được sử dụng với các công cụ sửa đổi bổ sung, chẳng hạn như $sort , $slice và $position , trong khi $addToSet không thể (ít nhất, không phải như MongoDB 4.4). |
Giá trị Hiện tại
Giả sử chúng ta có một bộ sưu tập với các tài liệu sau:
db.players.find()
Kết quả:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Hãy sử dụng $addToSet
để cố gắng nối một giá trị vào một trong các mảng.
db.players.update(
{ _id: 3 },
{ $addToSet: { scores: 5 } }
)
Đầu ra:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })
Điều này cho chúng tôi biết rằng có một tài liệu phù hợp (tài liệu 3), nhưng nó không được sửa đổi. Nó không được sửa đổi vì giá trị chúng tôi đã cố gắng chèn (5
) đã tồn tại trong mảng.
Hãy xem bộ sưu tập:
db.players.find()
Kết quả:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5 ] }
Như mong đợi, tài liệu 3 không bị thay đổi.
Hãy thử $push
thay vào đó:
db.players.update(
{ _id: 3 },
{ $push: { scores: 5 } }
)
Đầu ra:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Lần này, chúng tôi thấy rằng tài liệu đã được sửa đổi.
Chúng tôi có thể xác minh điều này bằng cách kiểm tra lại bộ sưu tập:
db.products.find()
Kết quả:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5 ] }
Công cụ sửa đổi
$push
toán tử có thể được sử dụng với các bổ ngữ như $position
, $sort
và $slice
.
$addToSet
không thể sử dụng toán tử với các công cụ sửa đổi này.
Đây là những gì sẽ xảy ra nếu tôi cố gắng sử dụng các công cụ sửa đổi này với $addToSet
:
db.players.update(
{ _id: 3 },
{
$addToSet: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Đầu ra:
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 }" } })
Thông báo lỗi cho chúng tôi biết rằng $position
, $sort
và $slice
là các trường không mong muốn (tức là chúng không nên ở đó).
Hãy thử cùng một công cụ sửa đổi với $push
:
db.players.update(
{ _id: 3 },
{
$push: {
scores: {
$each: [ 12 ],
$position: 0,
$sort: 1,
$slice: 5
}
}
}
)
Đầu ra:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Lần này nó hoạt động mà không có lỗi.
Xác minh kết quả:
db.players.find()
Kết quả:
{ "_id" : 1, "scores" : [ 1, 5, 3 ] } { "_id" : 2, "scores" : [ 8, 17, 18 ] } { "_id" : 3, "scores" : [ 3, 5, 5, 5, 12 ] }
Chúng ta có thể thấy rằng giá trị đã được thêm vào. Mặc dù chúng tôi đã chỉ định $position: 0
, chúng tôi cũng chỉ định $sort: 1
, có nghĩa là mảng đã được sắp xếp sau khi chúng tôi định vị nó.
Chúng tôi cũng chỉ định $slice: 5
, giới hạn mảng chỉ có 5 phần tử (hóa ra là chính xác có bao nhiêu phần tử trong mảng).