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

时间:2015-02-28 14:38:07

标签: 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")
             ]
        }
    ],
}

我希望删除所有ObjectId("54efe80bd6d5ca3d5c580a26"), 但我写了一个查询:

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

然后您的查询将如下所示。 (如果要更新多个文档,请记住添加{ "multi": true }作为选项。)

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

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

更新:使用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);
                });
            }
        }
    });
});