2015-09-26 43 views
2

我現在有下面這樣的格式的集合:MongoDB的:幾個字段列表

{ "_id": ObjectId(...), 
    "name" : "Name", 
    "red": 0, 
    "blue": 0, 
    "yellow": 1, 
    "green": 0, 
    ...} 

等(一堆顏色)。我想這樣做是爲了創建一個名爲colors新的數組,其元素是那些有1

的值。例如顏色:

{ "_id": ObjectId(...), 
    "name" : "Name", 
    "colors": ["yellow"] 
} 

這是不是我可以在做蒙戈貝殼?或者我應該在一個程序中做? 我很確定我可以用Python來完成,但是我很難直接在shell中執行它。如果它可以在shell中完成,任何人都可以指向正確的方向嗎?

謝謝。

回答

1

是的,它可以很容易地在shell中完成,或基本上通過遵循適用於任何語言的示例。

這裏的關鍵是查看「顏色」的字段,然後構造一個更新語句,既可以從文檔中刪除這些字段,同時測試它們以查看它們是否有效包含到數組中,然後添加這對文檔的更新,以及:

var bulk = db.collection.initializeOrderedBulkOp(), 
    count = 0; 

db.collection.find().forEach(function(doc) { 

    doc.colors = doc.colors || []; 

    var update = { "$unset": {}}; 
    Object.keys(doc).filter(function(key) { 
     return !/^_id|name|colors/.test(key) 
    }).forEach(function(key) { 
     update.$unset[key] = ""; 
     if (doc[key] == 1) 
      doc.colors.push(key); 
    }); 

    update["$addToSet"] = { "colors": { "$each": doc.colors } }; 

    bulk.find({ "_id": doc._id }).updateOne(update); 
    count++; 

    if (count % 1000 == 0) { 
     bulk.execute(); 
     bulk = db.collection.initializeOrderedBulkOp() 
    } 

}); 

if (count % 1000 != 0) 
    bulk.execute(); 

Bulk Operations使用意味着更新的批量發送,而不是一個請求,每個文件的響應,因此這將處理大量不僅僅是發出奇異的更新來回更快。

這裏的主要運營商是$unset刪除現有的字段和$addToSet添加新的評估數組。兩者都是通過循環構成可能顏色的文檔的按鍵來構建的,並排除您不想使用正則表達式過濾器修改的其他按鍵。

另外使用$addToSet和這一行:

doc.colors = doc.colors || []; 

享有作爲確信,如果任何文件已經部分轉化或通過已經開始存儲正確的數組碼變化,那麼這些否則觸摸的目的不會受到更新過程的不利影響或覆蓋。

1

tl;dr, spoiler

MongoDB的外殼可以訪問自己的對象的某些JavaScript的方法等。您可以使用db.yourCollectionName.find()查詢您的收藏集,這將返回一個光標(cursor methods)。然後迭代獲取每個文檔,遍歷這些鍵,有條件地過濾掉諸如_idname之類的鍵,然後檢查值是否爲1,將該鍵存儲在集合中的某處。

一旦這樣做,你可能想通過_id使用db.yourCollectionName.update()db.yourCollectionName.findAndModify()來查找記錄,並使用$set添加一個新的領域,並設置其值爲鍵的集合。