我在mongodb中有一个文件,包含一些数组。现在我需要一个包含此数组项目数量的字段。所以我需要更新添加此字段的文档。 我只是认为这会奏效:
db.myDocument.update({
"itemsTotal": {
$exists: false
},
"items": {
$exists: true
}
}, {
$set: {
itemsTotal: {
$size: "$items"
}
}
}, {
multi: true
})
但它完成了"而不是okForStorage"。 我也尝试进行聚合,但它会抛出异常:
"errmsg" : "exception: invalid operator '$size'",
"code" : 15999,
"ok" : 0
什么是最佳解决方案,我做错了什么?我开始考虑编写用于计算总计的Java工具并用它来更新文档。
答案 0 :(得分:1)
您可以初始化 Bulk()
操作构建器,以循环更新文档,如下所示:
var bulk = db.collection.initializeOrderedBulkOp(),
count = 0;
db.collection.find("itemsTotal": { "$exists": false },
"items": {
$exists: true
}
).forEach(function(doc) {
var items_size = doc.items.length;
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "itemsTotal": items_size }
});
count++;
if (count % 100 == 0) {
bulk.execute();
bulk = db.collection.initializeUnorderedBulkOp();
}
});
if (count % 100 != 0) { bulk.execute(); }
答案 1 :(得分:1)
您可以使用.aggregate()
方法$project
文档并返回items数组的$size
。之后,您需要使用.forEach
循环和$set
文档的itemTotal字段使用"Bulk"操作循环遍历汇总结果,以获得最高效率。
var bulkOp = db.myDocument.initializeUnorderedBulkOp();
var count = 0;
db.myDocument.aggregate([
{ "$match": {
"itemsTotal": { "$exists": false } ,
"items": { "$exists": true }
}},
{ "$project": { "itemsTotal": { "$size": "$items" } } }
]).forEach(function(doc) {
bulkOp.find({ "_id": doc._id }).updateOne({
"$set": { "itemsTotal": doc.itemsTotal }
});
count++;
if (count % 200 === 0) {
// Execute per 200 operations and re-init
bulkOp.execute();
bulkOp = db.myDocument.initializeUnorderedBulkOp();
}
})
// Clean up queues
if (count > 0) {
bulkOp.execute();
}
答案 2 :(得分:1)
从MongoDB v3.4开始更容易,该版本引入了$addFields
聚合管道运算符。我们还将使用$out
运算符将聚合结果输出到同一集合(replacing the existing collection is atomic)。
db.myDocuments.aggregate( [
{
$addFields: {
itemsTotal: { $size: "$items" } ,
},
},
{
$out: "myDocuments"
}
] )
警告:此解决方案要求所有文档具有items
字段。如果某些文档没有此文档,aggregate
将失败并
“ $ size的参数必须为数组,但类型为:缺少”
您可能会认为可以向聚合中添加$match
来仅过滤包含items
的文档,但这意味着所有包含items
的文档不都不会被输出回myDocuments
集合,这样您将永久丢失它们。