對於相對較小的數據,則可以通過使用其中您通過在$project
階段使用$setUnion
操作者創建具有不同品牌值的新陣列的聚合框架實現上述。如果數組包含重複條目,則$setUnion
將忽略重複的條目以及元素的順序。
一旦你獲得了新的不同品牌的領域,你會即它檢查給定的陣列是否使用相同的概念與$setUnion
運營商獨特的元素需要整個集合中用於過濾文檔的附加字段。從彙總的文件 使用效果陣列通過使用其forEach()
方法迭代結果光標和更新每個文件作如下更新您的收藏:
db.wholesalers.aggregate([
{
"$project": {
"distinctBrands": { "$setUnion": [ "$brands", [] ] },
"hasUniqueBrands": {
"$eq": [
{ "$size": "$brands" },
{ "$size": { "$setUnion": [ "$brands", [] ] } }
]
}
}
},
{ "$match": { "hasUniqueBrands": false } }
]).forEach(function(doc) {
db.wholesalers.update(
{ "_id": doc._id },
{ "$set": { "brands": doc.distinctBrands } }
)
})
雖然這是最適合於小集合,性能大型集合大大減少了,因爲循環遍歷大型數據集並將每個更新操作發送給服務器會導致計算懲罰。
Bulk()
由於寫入操作只發送給服務器一次,因此API可以幫助解決問題並大大提高性能。由於該方法不會向服務器發送每個寫入請求(如同循環中的當前更新語句那樣),但每1000次請求只發送一次,因此使得更新效率更高,速度更快。
使用上述與forEach()
循環創建批次相同的概念,我們可以在批量更新集合如下。
在該示範MongoDB中版本>= 2.6 and < 3.2
可用Bulk()
API使用initializeUnorderedBulkOp()
方法在平行於非確定性順序來執行,以及,在批寫入操作:
var bulk = db.wholesalers.initializeUnorderedBulkOp(),
counter = 0; // counter to keep track of the batch update size
db.wholesalers.aggregate([
{
"$project": {
"distinctBrands": { "$setUnion": [ "$brands", [] ] },
"hasUniqueBrands": {
"$eq": [
{ "$size": "$brands" },
{ "$size": { "$setUnion": [ "$brands", [] ] } }
]
}
}
},
{ "$match": { "hasUniqueBrands": false } }
]).forEach(function(doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "brands": doc.distinctBrands }
});
counter++; // increment counter
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations
// and re-initialize every 1000 update statements
bulk = db.wholesalers.initializeUnorderedBulkOp();
}
});
下一個示例適用於新的MongoDB版本3.2
,該版本從此棄用了Bulk()
API,並使用bulkWrite()
提供了一套更新的apis。
它使用與上述相同的光標,但使用相同的forEach()
遊標方法創建帶批量操作的陣列,以將每個批量寫入文檔推送到陣列。因爲寫命令可以接受不超過1000點的操作,還有的需要組操作有最多1000的操作和重新intialise數組時,迴路達到1000迭代:
var bulkUpdateOps = [];
db.wholesalers.aggregate([
{
"$project": {
"distinctBrands": { "$setUnion": [ "$brands", [] ] },
"hasUniqueBrands": {
"$eq": [
{ "$size": "$brands" },
{ "$size": { "$setUnion": [ "$brands", [] ] } }
]
}
}
},
{ "$match": { "hasUniqueBrands": false } }
]).forEach(function(doc){
bulkUpdateOps.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": { "$set": { "brands": doc.distinctBrands } }
}
});
if (bulkUpdateOps.length === 1000) {
db.wholesalers.bulkWrite(bulkUpdateOps);
bulkUpdateOps = [];
}
});
if (bulkUpdateOps.length > 0) { db.wholesalers.bulkWrite(bulkUpdateOps); }
你想要做的蒙戈的殼呢? – Mahdi
最簡單的方法是編寫腳本,它將更新所有記錄。並且將來你應該使用operator $ set來防止重複。 – Sabik