更新嵌套数组文档 [英] Update nested array document

查看:84
本文介绍了更新嵌套数组文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有这个模型

{
    _id : 1,
    ref: '1',
    children: [
    {
        ref:'1.1',
        grandchildren: [
            {
                ref:'1.1.1',
                visible: true;
            }
        ]
    }
    ]
}

我知道嵌套数组的位置运算符尚不可用.

I'm aware that positional operator for nested arrays isn't available yet.

https://jira.mongodb.org/browse/SERVER-831

但是想知道是否有可能原子地更新嵌套数组中的文档?

but wondered whether its possible to atomically update the document in the nested array?

在我的示例中,我想将参考文件1.1.1的文档的visible标志更新为false.

In my example, i'd like to update the visible flag to false for the document for ref 1.1.1.

我有孩子记录ref =='1.1'和孙子记录ref =='1.1.1'

I have the children record ref == '1.1' and the grandchildrenref == '1.1.1'

谢谢

推荐答案

是的,只有当您知道预先拥有孙对象的子数组的索引并且更新查询将使用位置运算符时,才有可能如下:

Yes, this is possible only if you knew the index of the children array that has the grandchildren object to be updated beforehand and the update query will use the positional operator as follows:

db.collection.update(
    {
        "children.ref": "1.1",
        "children.grandchildren.ref": "1.1.1"
    }, 
    {
        "$set": { 
            "children.0.grandchildren.$.visible": false
        }
    }
)

但是,如果您事先不知道数组索引的位置,则应该考虑使用 $set 条件. mongodb.org/manual/core/map-reduce/"rel =" nofollow> MapReduce . MapReduce的基本思想是它使用JavaScript作为查询语言,但是它比聚合框架要慢得多,因此不建议在实时数​​据分析中使用.

However, if you don't know the array index positions beforehand, you should consider creating the $set conditions dynamically by using MapReduce. The basic idea with MapReduce is that it uses JavaScript as its query language but this tends to be fairly slower than the aggregation framework and not recommended for use in real-time data analysis.

在MapReduce操作中,您需要定义几个步骤,即映射步骤(将操作映射到集合中每个文档的映射步骤,该操作要么不执行任何操作,要么不发出任何带有键和投影值的对象),并且减少步骤(将发出的值的列表减少到一个元素).

In your MapReduce operation, you need to define a couple of steps i.e. the mapping step (which maps an operation into every document in the collection, and the operation can either do nothing or emit some object with keys and projected values) and reducing step (which takes the list of emitted values and reduces it to a single element).

对于映射步骤,理想情况下,您希望获取集合中的每个文档,每个children数组字段的索引以及另一个包含$set键的键.

For the map step, you ideally would want to get for every document in the collection, the index for each children array field and another key that contains the $set keys.

您的reduce步骤将是一个简单定义为var reduce = function() {};

Your reduce step would be a function (which does nothing) simply defined as var reduce = function() {};

然后,MapReduce操作的最后一步将创建一个单独的收集操作,该操作包含发出的操作数组对象以及具有$set条件的字段.在原始集合上运行MapReduce操作时,可以定期更新此集合. 总而言之,此MapReduce方法如下所示:

The final step in your MapReduce operation will then create a separate collection operations that contains the emitted operations array object along with a field with the $set conditions. This collection can be updated periodically when you run the MapReduce operation on the original collection. Altogether, this MapReduce method would look like:

var map = function(){
    for(var i = 0; i < this.children.length; i++){
        emit( 
            {
                "_id": this._id, 
                "index": i 
            }, 
            {
                "index": i, 
                "children": this.children[i],            
                "update": {
                    "ref": "children." + i.toString() + ".grandchildren.$.ref",
                    "visible": "children." + i.toString() + ".grandchildren.$.visible"
                }                    
            }
        );
    }
};

var reduce = function(){};

db.collection.mapReduce(
    map,
    reduce,
    {
        "out": {
            "replace": "update_collection"
        }
    }
);

然后您可以使用db.update_collection.find()方法中的游标进行迭代并相应地更新您的收藏集:

You can then use the cursor from the db.update_collection.find() method to iterate over and update your collection accordingly:

var cur = db.update_collection.find(
    {
        "value.children.ref": "1.1",
        "value.children.grandchildren.ref": "1.1.1" 
    }
);

// Iterate through results and update using the update query object set dynamically by using the array-index syntax.
while (cur.hasNext()) {
    var doc = cur.next();
    var update = { "$set": {} };
    // set the update query object
    update["$set"][doc.value.update.visible] = false;

    db.collection.update(
        {
            "children.ref": "1.1",
            "children.grandchildren.ref": "1.1.1"
        }, 
        update 
    );
};

这篇关于更新嵌套数组文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆