2013-01-31 100 views
2

我在MongoDb的查詢和更新選擇器的叢林中糾結了一下。如何更新數組中的字段,僅當其他字段與MongoDB中的值匹配

情況:我們有公司收集。像這樣這樣的

Companies.find({}) => 
{_id: 1, item_amount: 5}, 
{_id: 2, item_amount: 7}, 
{_id: 3, item_amount: 10} 

而且我們有一些結構的用戶集合。用戶想要購買任何商品,並且它可能會減少公司中的價值並在用戶中增加,但有一個條件 - 用戶可能知道他在哪裏購買商品。

{userId: _id, 
ownedItems: 
    [{company_id: 2, item_amount: 3}, 
    {company_id: 1, item_amount: 5}] 
} 

好的。我怎麼可能Users.update(),如果用戶想從{_id: 3}購買,例如,5個項目(我們不知道,如果用戶擁有領域company_id: 3

我想這可能是水木清華這樣的:

Companies.update({_id: 3}, {$inc: {item_amount: - 5}})
& &
Users.update({userId: _id}, {$set: {'ownedItems[x].company_id': 3}, $inc{'ownedItems[x].item_amount': 5})

原因,但也存在一些問題。
我怎麼知道每個clint的[x]?把它分類?如果我需要添加新公司,該怎麼辦?
是否$set將工作,如果字段'ownedItems[x].company_id'不存在?

可能我可能會檢查IF/Else語句中的錯誤。例如,使用$exist$cond(用於彙總)選擇器。但.find()總是返回一個遊標(是嗎?),而不是真或假。那麼可能會做什麼?我如何使用聚合選擇器?就像這樣:

Users.find({_id: userId}, {$cond: [{$eq: ['owenedItem[x].company_id', _someId_]}, {$set:{...}}, {$push: {...}}]})

將它的工作?

回答

3

聽起來像是你要使用的$ elemMatch運營商結合 '$' 定位符:

http://docs.mongodb.org/manual/reference/operator/elemMatch/ http://docs.mongodb.org/manual/reference/operator/positional/

讓我們把你的例子。假設您想在用戶的「ownedItems」列表中找到「company_id」爲3的元素,並將該元素的「item_amount」更新爲5.這可以在單個更新語句中完成,如下所示:

Users.update({ userId: _id, ownedItems : { $elemMatch : { company_id : 3 } } }, 
       { $inc : { ownedItems.$.item_amount : 5 } }) 

$ elemMatch運算符使其明確列出要查詢的列表中的哪些元素。然後,您可以在修飾語子句中使用$運算符來引用該匹配元素並對其進行更改。

如果用戶的「ownedItems」列表中沒有任何匹配{「company_id」:3}的條目,那麼上述更新將不會執行任何操作。如果出現這種情況,你可以做第二次更新與$ addToSet運營商增加新的項目,像這樣:

Users.update({ userId: _id }, 
       { $addToSet : { ownedItems : { company_id : 3, item_amount : 5 } } }) 

http://docs.mongodb.org/manual/reference/operator/addToSet/

+0

感謝您的回答!但也許我錯過了一些事情。我在這裏看到我的例子有2個問題。首先,我不知道Users集合是否有'company_id',如果用戶doc中沒有字段會發生什麼。和第二個'問題',可能是我不熟悉** $ **運算符,但正如我認爲它返回查詢的數組的**第一**匹配,所以在數組中,它可以增加值,例如,company_id = 1,如果它將成爲查詢的第一個匹配(抱歉,這麼愚蠢的問題:))? – Pruntoff

+0

好點!在這種情況下,你必須做2次更新。您可以檢查我提到的原始更新的結果,如果它實際上沒有更改任何內容(因爲查詢不匹配),則執行另一個使用$ addToSet的更新以將新條目添加到ownedItems列表中。我會更新我的答案與細節。我不確定我瞭解你的第二個問題。這是否會增加列表中的第一個匹配的問題?您是否期望列表中的多個條目具有相同的company_id? – robert

相關問題