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

Ris*_*arg 5 mongodb

我的文档包含一个数组,如:

{
    "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")
             ]
        }
    ],
}
Run Code Online (Sandbox Code Playgroud)

我想删除所有出现的ObjectId("54efe80bd6d5ca3d5c580a26"),但我写了一个查询:

db.ekgs.update({'interpretationList.interpretations':ObjectId("54c09fb3581c4c8c218d1a40")}, {$pull:{ 'interpretationList.$.interpretations':{ ObjectId("54c09fb3581c4c8c218d1a40")}})
Run Code Online (Sandbox Code Playgroud)

仅删除第一次出现ObjectId("54efe80bd6d5ca3d5c580a26")

Jua*_*rah 0

您的查询仅删除第一个匹配项的原因是,如文档中本页所述,“位置$运算符充当与查询文档匹配的第一个元素的占位符”。

问题在于,使用嵌入数组中的嵌入对象中的嵌入数组的模式来处理这些类型的更新确实很棘手。为了解决这个问题,如果您能够扁平化架构,那么您的更新就会变得更加容易。因此,如果您的文档看起来像这样:

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

那么您的查询将像下面一样简单。(如果您想更新多个文档,请记住添加{ "multi": true }为选项)。

db.ekgs.update(
    { "interpretations": ObjectId("54efe80bd6d5ca3d5c580a26")},
    { "$pull": { "interpretations": ObjectId("54efe80bd6d5ca3d5c580a26") }}
);
Run Code Online (Sandbox Code Playgroud)

但我知道您可能无法更改架构。在这种情况下,您可以尝试需要小脚本的解决方案。在mongoshell 中,您可以使用以下 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 }});
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:使用 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);
                });
            }
        }
    });
});
Run Code Online (Sandbox Code Playgroud)