我的文档如下所示,我只想在售出的数量少于总数字段时更新已售出的字段。我知道如何在文档数组中检索文档,我知道如何比较文档中的两个字段,但我不知道如何在一个单独的表达式中与更新一起完成它们。
{
"_id" : ObjectId("4f7ee46e08403d063ab0b4f9"),
"name" : "MongoDB",
"notes" : [
{
"_Id" : ObjectId("4f7ee46e08403d063ab0h659")
"title" : "Hello MongoDB",
"content" : "Hello MongoDB",
"total" : 100
},
{
"_Id" : ObjectId("4f7ee46e08403d083ab0h659")
"title" : "ReplicaSet MongoDB",
"content" : "ReplicaSet MongoDB",
"total" : 200,
"sold" : 2
},
{
"_Id" : ObjectId("4f7ee65e08403d083ab0h659")
"title" : "ReplicaSet MongoDB",
"content" : "ReplicaSet MongoDB",
"total" : 200,
}
]
}
我的表达式是从文档数组中读取文档:
db.Collection.find({'notes._id':ObjectId('58791af46c698c00475e7f41')},{'notes.$':true})
我可以写一个这样的表达式来比较两个字段
db.Collection.find( { $where : "this.total > this.sold" });
答案 0 :(得分:0)
最好的方法是首先使用聚合作为确定文档列表的方法,以及与给定条件匹配的数组元素的子集,即销售量小于总字段数。 获得此列表后,您可以处理批量更新,这将至少允许在单个请求中使用单一响应发送许多操作。
以下示例说明了如何解决此问题:
var ops = [],
cursor = db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$allElementsTrue": {
"$map": {
"input": "$notes",
"as": "el",
"in": { "$gt": [ "$$el.total", "$$el.sold" ] }
}
}
},
"$$KEEP",
"$$PRUNE"
]
}
},
{
"$project": {
"notes": {
"$filter": {
"input": "$notes",
"as": "el",
"cond": {
"$and": [
{ "$gt": [ "$$el.total", "$$el.sold" ] },
{ "$gt": [ "$$el.sold", null ] }
]
}
}
}
}
}
]);
cursor.forEach(function(doc) {
doc.notes.forEach(function(note){
ops.push({
"updateOne": {
"filter": { "_id": doc._id, "notes._id": note._id },
"update": {
"$set": { "notes.$.sold": 400 } // update the sold field accordingly
}
}
});
if (ops.length === 500 ) {
db.collection.bulkWrite(ops);
ops = [];
}
});
})
if (ops.length > 0)
db.collection.bulkWrite(ops);