2013-10-15 141 views
10

我已經收集了許多類似的結構化文檔更新,兩個文件看起來像聚集在MongoDB中

輸入:

{ 
    "_id": ObjectId("525c22348771ebd7b179add8"), 
    "cust_id": "A1234", 
    "score": 500, 
    "status": "A" 
    "clear": "No" 
} 

{ 
    "_id": ObjectId("525c22348771ebd7b179add9"), 
    "cust_id": "A1234", 
    "score": 1600, 
    "status": "B" 
    "clear": "No" 
} 

默認情況下,clear所有文檔"No"

請求:我必須添加相同的所有文檔的得分cust_id,只要它們屬於status"A"status"B"。如果score超過2000那麼我必須更新clear屬性爲"Yes"對於所有具有相同cust_id的文檔。

預期輸出:

{ 
    "_id": ObjectId("525c22348771ebd7b179add8"), 
    "cust_id": "A1234", 
    "score": 500, 
    "status": "A" 
    "clear": "Yes" 
} 

{ 
    "_id": ObjectId("525c22348771ebd7b179add9"), 
    "cust_id": "A1234", 
    "score": 1600, 
    "status": "B" 
    "clear": "Yes" 
} 

是因爲1600 + 500 = 2100和2100> 2000


我的方法: 我只能通過聚合函數得到的總和,但更新失敗

db.aggregation.aggregate([ 
    {$match: { 
     $or: [ 
      {status: 'A'}, 
      {status: 'B'} 
     ] 
    }}, 
    {$group: { 
     _id: '$cust_id', 
     total: {$sum: '$score'} 
    }}, 
    {$match: { 
     total: {$gt: 2000} 
    }} 
]) 

請告訴我該怎麼做。

感謝提前:)

+0

你能描述失敗是怎麼發生的嗎?有沒有錯誤,或類似的東西? –

+0

沒有錯誤本身,但我發現很難有一個聲明中的更新和聚合函數在一起,我對mongodb很新,我正在嘗試cmd中的場景。 – Sam

回答

10

了很大的麻煩後,實驗蒙戈貝殼,我終於得到了解決我的問題。

Psudocode:

# To get the list of customer whose score is greater than 2000 
cust_to_clear=db.col.aggregate(
    {$match:{$or:[{status:'A'},{status:'B'}]}}, 
    {$group:{_id:'$cust_id',total:{$sum:'$score'}}}, 
    {$match:{total:{$gt:500}}}) 

# To loop through the result fetched from above code and update the clear 
cust_to_clear.result.forEach 
(
    function(x) 
    { 
    db.col.update({cust_id:x._id},{$set:{clear:'Yes'}},{multi:true}); 
    } 
) 

請發表評論,如果您有同樣的問題,任何不同的解決方案。

5

你需要做這兩個步驟:

  1. 識別客戶(cust_id)以總成績高於200
  2. 對於這些客戶,設置clearYes

對於第一部分,您已經有了一個很好的解決方案。第二部分應作爲單獨的update()調用實現到數據庫。

Psudocode:

# Get list of customers using the aggregation framework 
cust_to_clear = db.col.aggregate(
    {$match:{$or:[{status:'A'},{status:'B'}]}}, 
    {$group:{_id:'$cust_id', total:{$sum:'$score'}}}, 
    {$match:{total:{$gt:2000}}} 
    ) 

# Loop over customers and update "clear" to "yes" 
for customer in cust_to_clear: 
    id = customer[_id] 
    db.col.update(
     {"_id": id}, 
     {"$set": {"clear": "Yes"}} 
    ) 

,因爲你必須做一個數據庫調用爲每一位顧客這是不理想的。如果您需要經常進行這種操作,您可以修改您的模式以在每個文檔中包含總分。 (這必須由應用程序維護。)在這種情況下,你可以做的更新使用一個命令:

db.col.update(
    {"total_score": {"$gt": 2000}}, 
    {"$set": {"clear": "Yes"}}, 
    {"multi": true} 
    ) 
+0

嗨,感謝您的解決方案,我一直在嘗試運行上面的代碼,它給了我一些錯誤。 1.語法錯誤:意外標識符,2.不能在查詢表達式中定義。你能否以格式編寫完整的代碼,因爲我實際上是mongoDB的新手。 – Sam

+0

我使用了psudocode,因爲它需要在應用程序級別上實現,並且您不指定使用哪個驅動程序。我可以做一個Python(pymongo)版本,或者找出一種方法來直接使用Mongo shell的腳本。哪些會更有幫助? – SuperAce99

+0

我想通過cmd運行代碼我猜腳本爲mongo shell直接會幫助。我試圖通過嘗試不同的場景來探索mongo的功能。你能不能也請給我建議一個很好的界面來處理mongo,因爲cmd是非常令人沮喪的。 – Sam