简体   繁体   English

从MongoDB中的数组中删除多个文档

[英]Remove multiple documents from array in MongoDB

My document contains an array like: 我的文档包含如下数组:

{
    "differentialDiagnosis" : "IART/Flutter",
    "explanation" : "The rhythm.",
    "fileName" : "A115a JPEG.jpg",
    "history" : "1 year old with fussiness",
    "interpretationList" : [ 
        {
           "interpretations" : [
                ObjectId("54efe7c8d6d5ca3d5c580a22"), 
                ObjectId("54efe80bd6d5ca3d5c580a26")
            ]
        }, 
        {
            "interpretations" : [ 
                ObjectId("54efe80bd6d5ca3d5c580a26"), 
                ObjectId("54efe82ad6d5ca3d5c580a28")
             ]
        }
    ],
}

and I want to remove all occurrences of ObjectId("54efe80bd6d5ca3d5c580a26") , but I write a query: 我想删除所有出现的ObjectId("54efe80bd6d5ca3d5c580a26") ,但我写了一个查询:

db.ekgs.update({'interpretationList.interpretations':ObjectId("54c09fb3581c4c8c218d1a40")}, {$pull:{ 'interpretationList.$.interpretations':{ ObjectId("54c09fb3581c4c8c218d1a40")}})

This removes only first occurrence of ObjectId("54efe80bd6d5ca3d5c580a26") . 仅删除第一次出现ObjectId("54efe80bd6d5ca3d5c580a26")

The reason your query is only removing the first occurrence is because, as explained in this page in the documentation, "the positional $ operator acts as a placeholder for the first element that matches the query document". 您的查询仅删除第一次出现的原因是,正如文档中的此页面所述,“位置$运算符充当与查询文档匹配的第一个元素的占位符”。

The problem is that it is really tricky to deal with these types of updates with schema having embedded arrays in embedded objects in embedded arrays. 问题在于,在嵌入式阵列的嵌入式对象中使用嵌入式数组的模式处理这些类型的更新是非常棘手的。 In order to get around this problem, if you are able to flatten the schema, then your update becomes much easier. 为了解决这个问题,如果您能够展平架构,那么您的更新将变得更加容易。 So if instead, your document looked like this: 因此,如果相反,您的文档看起来像这样:

{
    "differentialDiagnosis" : "IART/Flutter",
    "explanation" : "The rhythm.",
    "fileName" : "A115a JPEG.jpg",
    "history" : "1 year old with fussiness",
    "interpretations" : [
        ObjectId("54efe7c8d6d5ca3d5c580a22"), 
        ObjectId("54efe80bd6d5ca3d5c580a26"),
        ObjectId("54efe82ad6d5ca3d5c580a28")
    ]
}

Then your query would be as simple as the one below. 那么你的查询就像下面那样简单。 (Remember to add { "multi": true } as an option if you want to update multiple documents). (如果要更新多个文档,请记住添加{ "multi": true }作为选项)。

db.ekgs.update(
    { "interpretations": ObjectId("54efe80bd6d5ca3d5c580a26")},
    { "$pull": { "interpretations": ObjectId("54efe80bd6d5ca3d5c580a26") }}
);

But I understand that you might not be able to change the schema. 但我知道您可能无法更改架构。 In that case, you can try a solution that requires a small script. 在这种情况下,您可以尝试需要小脚本的解决方案。 In the mongo shell, you can use the following bit of JavaScript to do the operation. mongo shell中,您可以使用以下JavaScript来执行操作。

// Get cursor with documents requiring updating.
var oid = ObjectId("54efe80bd6d5ca3d5c580a26");
var c = db.ekgs.find({ "interpretationList.interpretations": oid });

// Iterate through cursor, removing oid from each subdocument in interpretationList.
while (c.hasNext()) {
    var isModified = false;
    var doc = c.next(); 
    var il = doc.interpretationList;
    for (var i in il) {
        var j = il[i].interpretations.length;
        while (j--) {

            // If oid to remove is present, remove it from array
            // and set flag that the document has been modified.
            if (il[i].interpretations[j].str === oid.str) {
                il[i].interpretations.splice(j, 1);
                isModified = true;
            }
        }
    }

    // If modified, update interpretationList for document.
    if (isModified) {
        db.ekgs.update({ "_id": doc._id }, { "$set": { "interpretationList": il }});
    }
}

UPDATE: Example of how it might work using the Node.js driver. 更新:使用Node.js驱动程序如何工作的示例。

// Get cursor with documents requiring updating.
var oid = new ObjectID("54efe80bd6d5ca3d5c580a26");
var ekgs = db.collection("ekgs");
ekgs.find({ "interpretationList.interpretations": oid },
          function(err, c) {    

    if(err) throw err;

    // Iterate through cursor, removing oid from each subdocument in interpretationList.
    c.each(function(err, doc) {
        if (err) throw err;

        // If doc is null then the cursor is exhausted/empty and closed.
        if (doc != null) {
            var isModified = false;         
            var il = doc.interpretationList;
            for (var i in il) {
                var j = il[i].interpretations.length;
                while (j--) {

                    // If oid to remove is present, remove it from array
                    // and set flag that the document has been modified.
                    if (il[i].interpretations[j].equals(oid)) {                         
                        il[i].interpretations.splice(j, 1);
                        isModified = true;
                    }
                }
            }           

            // If modified, update interpretationList for document.
            if (isModified) {
                ekgs.update({ "_id": doc._id },
                            { "$set": { "interpretationList": il }},
                            function(err, res) {

                    if (err) throw err;

                    // Callback.
                    console.log(res);
                });
            }
        }
    });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM