使用$ where和$和更新数组内的文档

时间:2017-01-16 22:21:48

标签: mongodb

我的文档如下所示,我只想在售出的数量少于总数字段时更新已售出的字段。我知道如何在文档数组中检索文档,我知道如何比较文档中的两个字段,但我不知道如何在一个单独的表达式中与更新一起完成它们。

{
"_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" });

1 个答案:

答案 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);
相关问题