当前位置: 首页 > 知识库问答 >
问题:

正在更新数组mongodb中的嵌套数组[重复]

顾穆冉
2023-03-14

我有以下mongodb文档结构:

[
    {
        "_id": "04",
        "name": "test service 4",
        "id": "04",
        "version": "0.0.1",
        "title": "testing",
        "description": "test",
        "protocol": "test",
        "operations": [
            {
                "_id": "99",
                "oName": "test op 52222222222",
                "sid": "04",
                "name": "test op 52222222222",
                "oid": "99",
                "description": "testing",
                "returntype": "test",
                "parameters": [
                    {
                        "oName": "Param1",
                        "name": "Param1",
                        "pid": "011",
                        "type": "582",
                        "description": "testing",
                        "value": ""
                    },
                    {
                        "oName": "Param2",
                        "name": "Param2",
                        "pid": "012",
                        "type": "58222",
                        "description": "testing",
                        "value": ""
                    }
                ]
            }
        ]
    }
]

我已经能够使用$elemMatch来更新操作中的字段,但当我尝试对参数执行相同的操作(修改)时,它似乎不起作用。我想知道,为了能够通过pid查找特定参数中的字段,我应该尝试其他什么方法来成功更新字段。

我目前拥有但不起作用的更新代码如下所示:

var oid = req.params.operations;
var pid = req.params.parameters;

collection.update({"parameters":{"$elemMatch": {"pid": pid}}},{"$set": {"parameters.$.name":req.body.name, "parameters.$.description": req.body.description,"parameters.$.oName": req.body.oName,"parameters.$.type": req.body.type} }, function(err, result) {
        if (err) {
            console.log('Error updating service: ' + err);
            res.send({'error':'An error has occurred'});
        } else {
            // console.log('' + result + ' document(s) updated');
            res.send(result);
        }
    });

共有3个答案

慕佑运
2023-03-14

我们将尝试查找外部数组(i)和内部数组(j)的索引,然后更新

collection.findById(04)
.then(result =>{
    for(let i = 0; i<result.operations.length; i++){
        if(result.operation[i]._id == "99"){
            let parameters = result.operations[i].parameters;`enter code here`
            for(let j = 0; j<parameters.length; j++){
                if(parameters[j].pid == "011"){
                    console.log("i", i);
                    console.log("j", j);
                    let data = {}
                    data["operations." + i + ".parameters." + j + ".oName"] = updateoName
                    data["operations." + i + ".parameters." + j + ".name"] = updatename
                    data["operations." + i + ".parameters." + j + ".pid"] = updatepid
                    data["operations." + i + ".parameters." + j + ".description"] = updatedescription
                    data["operations." + i + ".parameters." + j + ".value"] = updatevalue
                    console.log(data)
                    collection.update({
                        "_id": "04"
                    },{
                        $set: data
                    })
                    .then(dbModel => res.json(dbModel))
                }
            }
        }
    }
})
戈睿识
2023-03-14

如果是经常更改的数据,则应将结构扁平化,并将变化较大的数据与变化不大的数据分开。

如果是不经常更改的数据,并且整个数据对象不是海量的,那么只需在客户端修改对象,并更新整个对象。

益楷
2023-03-14

MongoDB 3.6及更高版本提供了一个新功能,允许您使用位置过滤的$\[更新嵌套数组

const { oid, pid } = req.params;
const { name, oName, description, type } = req.body; 

collection.update(
    {
        "_id": 1,
        "operations": {
            "$elemMatch": {
                oid, "parameters.pid": pid
            }
        }
    },
    { "$set": { 
        "operations.$[outer].parameters.$[inner].name": name,
        "operations.$[outer].parameters.$[inner].description": description,
        "operations.$[outer].parameters.$[inner].oName": oName,
        "operations.$[outer].parameters.$[inner].type": type 
    } },
    { "arrayFilters": [
        { "outer.oid": oid },
        { "inner.pid": pid }
    ] }, (err, result) => {
    if (err) {
        console.log('Error updating service: ' + err);
        res.send({'error':'An error has occurred'});
    } else {
        // console.log('' + result + ' document(s) updated');
        res.send(result);
    }
});

正如@wdberkeley在评论中提到的:

MongoDB不支持匹配到数组的多个级别。考虑更改文档模型,以便每个文档代表一个操作,操作文档中复制了一组操作的公共信息。

我同意上述观点,并建议重新设计您的模式,因为MongoDB引擎不支持多个位置操作符(请参阅多次使用位置操作符来更新嵌套数组)

但是,如果您知道具有要提前更新的参数对象的操作数组的索引,则更新查询将是:

db.collection.update(
    {
        "_id" : "04", 
        "operations.parameters.pid": "011"
    }, 
    {
        "$set": { 
            "operations.0.parameters.$.name": "foo",
            "operations.0.parameters.$.description": "bar", 
            "operations.0.parameters.$.type": "foo" 
        }
    }
)

编辑:

如果您想动态创建$set条件,即帮助您获取对象的索引,然后进行相应修改,那么可以考虑使用MapReduce。

目前,使用聚合框架似乎不可能做到这一点。与之相关的是一个尚未解决的JIRA未决问题。但是,可以使用MapReduce解决问题。MapReduce的基本思想是使用JavaScript作为其查询语言,但这往往比聚合框架慢得多,不应用于实时数据分析。

在MapReduce操作中,需要定义两个步骤,即映射步骤(该步骤将操作映射到集合中的每个文档中,该操作可以不执行任何操作,也可以发射一些具有键和投影值的对象)和缩减步骤(该步骤获取发射值的列表并将其缩减为单个元素)。

对于映射步骤,理想情况下,您希望为集合中的每个文档获取每个操作数组字段的索引和另一个包含设置键的键。

您的reduce步骤将是一个函数(它什么都不做),简单地定义为var reduce=function(){}

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

var map = function(){
    for(var i = 0; i < this.operations.length; i++){
        emit( 
            {
                "_id": this._id, 
                "index": i 
            }, 
            {
                "index": i, 
                "operations": this.operations[i],            
                "update": {
                    "name": "operations." + i.toString() + ".parameters.$.name",
                    "description": "operations." + i.toString() + ".parameters.$.description",
                    "type": "operations." + i.toString() + ".parameters.$.type"
                }                    
            }
        );
    }
};

var reduce = function(){};

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

从MapReduce操作查询输出集合操作通常会得到以下结果:

db.operations.findOne()

输出:

{
    "_id" : {
        "_id" : "03",
        "index" : 0
    },
    "value" : {
        "index" : 0,
        "operations" : {
            "_id" : "96",
            "oName" : "test op 52222222222",
            "sid" : "04",
            "name" : "test op 52222222222",
            "oid" : "99",
            "description" : "testing",
            "returntype" : "test",
            "parameters" : [ 
                {
                    "oName" : "Param1",
                    "name" : "foo",
                    "pid" : "011",
                    "type" : "foo",
                    "description" : "bar",
                    "value" : ""
                }, 
                {
                    "oName" : "Param2",
                    "name" : "Param2",
                    "pid" : "012",
                    "type" : "58222",
                    "description" : "testing",
                    "value" : ""
                }
            ]
        },
        "update" : {
            "name" : "operations.0.parameters.$.name",
            "description" : "operations.0.parameters.$.description",
            "type" : "operations.0.parameters.$.type"
        }
    }
}

然后可以使用数据库中的光标。操作。find()方法迭代并相应更新集合:

var oid = req.params.operations;
var pid = req.params.parameters;
var cur = db.operations.find({"_id._id": oid, "value.operations.parameters.pid": pid });

// 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.name] = req.body.name;
    update["$set"][doc.value.update.description] = req.body.description;
    update["$set"][doc.value.update.type] = req.body.type;

    db.collection.update(
        {
            "_id" : oid, 
            "operations.parameters.pid": pid
        }, 
        update 
    );
};

 类似资料:
  • 我有以下JSON: 我希望能够将内容推送到与迭代 2 关联的任务数组中。如何正确查询并插入到正确的位置?这就是我到目前为止所拥有的,但它总是插入到与迭代 1 关联的任务数组中。 我已经看到了这个:MongoDB嵌套数组查询,但他只是试图推送到一个嵌套数组。

  • 问题内容: 我有以下mongodb文件结构: 我已经能够使用$ elemMatch来更新操作中的字段,但是当我尝试对参数执行相同的操作(修改)时,它似乎不起作用。我想知道我应该尝试哪种其他方法,以便能够成功更新特定参数中的字段(通过其pid查找)。 我当前拥有但不起作用的更新代码如下所示: 问题答案: MongoDB 3.6及更高版本 MongoDB3.6及更高版本提供了一项新功能,该功能允许您使

  • 我正在尝试更新嵌套数组中的值,但无法使其工作。 我的对象是这样的 提前谢谢!

  • 我正在使用平均堆栈在网格中显示以下数组。 嵌套数组:

  • 问题内容: 我正在尝试更新嵌套数组中的值,但无法使其正常工作。 我的对象是这样的 我需要将值推送到“ answeredBy”数组。 在下面的示例中,我尝试将“成功”字符串推到“ 123 _id”对象的“ answeredBy”数组中,但是它不起作用。 我找到了此链接,但其答案仅表示我应该使用类似结构的对象而不是数组。这不适用于我的情况。我真的需要将我的对象嵌套在数组中 如果您能在这里帮助我,那就太

  • 我需要更新嵌套在我的用户文档中的一个字段,该字段包含一个part对象数组,以添加新的part。一个part对象如下所示: 所以这意味着$addToset对我的情况没有好处...现在我不知道该怎么办。