的MongoDB不允許兩者$pull
和$push
或任何其它操作,以在單個語句更新相同的「路徑」(因此單個陣列)。這主要與邏輯處理服務器端有關,更新操作從未被視爲在語句中被排序。
例子:
{
"responses": [
{ "user": "Tom", "status": "like" },
{ "user": "Sarah", "status": "unlike" }
]
}
不在於它會多大意義,但你不能做到這一點:
db.collection.update(
{},
{
"$pull": { "responses": { "user": "Tom", "status": "like" },
"$push": { "responses": { "user": "Tom", "status": "unlike" }
}
)
由於這裏的單人操作包含「相同的路徑」兩個$push
和$pull
作爲「迴應」。無論你如何構造聲明,都不需要以任何順序執行。
雖然我們可以「投其所好」的「湯姆」的位置,並改變了他的「身份」到「不像」代替,一個更好的模式是這樣:
{
"likes": ["Tom"],
"unlikes": ["Sarah"],
"likesTotal": 1,
"unlikesTotal": 1,
"totalScore": 0
}
這意味着如果我想更改「湯姆」的「投票」,那麼你做一個結構就是這樣,有Bulk操作的幫助,以使單個請求和響應:
var bulk = db.collection.initializeOrderedBulkOp();
// Cast "Tom's" unlike where they had a "like" already
bulk.find({
"likes": "Tom",
"unlikes": { "$ne": "Tom" }
}).updateOne({
"$pull": { "likes": "Tom" },
"$push": { "unlikes": "Tom" },
"$inc": {
"likesTotal": -1,
"unlikesTotal": 1
}
]);
// Cast "Tom's" new vote where nothing was there at all
bulk.find({
"unlikes": { "$ne": "Tom" },
"likes": { "$ne": "Tom" }
}).updateOne({
"$push": { "unlikes": "Tom" },
"$inc": {
"unlikesTotal": 1,
"totalScore": -1
}
});
bulk.execute();
這將產生一個非常好的模式。不僅每個更新操作在這裏基本上都是「原子」的,因爲通過作用於單獨的文檔屬性,每個修飾符被允許執行而不會發生衝突。而且作爲一個「批量」操作,爲滿足這裏所有可能的條件「既」更新操作的要求在單個請求被髮送,並在單個響應接收。
當然你的「客戶」的邏輯也應該知道的關於特定項目誰已經「喜歡/不喜歡的」,但一般API中執行,這是很好的做法目前的狀態。
它保持在檢查陣列,並且還保持有用計數器在檢查用於一般數據和一般查詢的目的,而不需要「計算」陣列或匹配的類型的長度。
@JohnnyHK現在你明白我的需要? – Kashif