【问题标题】:Updating Nested Array Mongoose更新嵌套数组 Mongoose
【发布时间】:2017-01-24 03:35:28
【问题描述】:

我正在开发一个需要更新嵌套数组的 express js 应用程序。 1) 架构:

//Creating a mongoose schema
var userSchema = mongoose.Schema({
_id: {type: String, required:true},
name: String,
sensors: [{
    sensor_name: {type: String, required:true},
    measurements: [{time: String}]
}] });

2) 这是代码sn-p,解释如下:

router.route('/sensors_update/:_id/:sensor_name/')
.post(function (req, res) {
User.findOneAndUpdate({_id:req.body._id}, {$push: {"sensors" : 
{"sensor_name" : req.body.sensor_name , "measurements.0.time": req.body.time } } },
{new:true},function(err, newSensor) {
if (err)
res.send(err);
res.send(newSensor)
}); });

我能够使用带有推送技术的 findOneAndUpdate 成功将值更新到测量数组,但是当我尝试将多个测量添加到传感器数组时失败了。

这是我在向传感器阵列发布第二次测量时得到的当前 json:

{
"_id": "Manasa",
"name": "Manasa Sub",
"__v": 0,
"sensors": [
{
  "sensor_name": "ras",
  "_id": "57da0a4bf3884d1fb2234c74",
  "measurements": [
    {
      "time": "8:00"
    }
  ]
},
{
  "sensor_name": "ras",
  "_id": "57da0a68f3884d1fb2234c75",
  "measurements": [
    {
      "time": "9:00"
    }
  ]
  }]} 

但我想要的正确格式是使用传感器阵列发布多个测量值,如下所示:

正确的 JSON 格式应该是:

 {
"_id" : "Manasa",
"name" : "Manasa Sub",
"sensors" : [ 
    {
        "sensor_name" : "ras",
        "_id" : ObjectId("57da0a4bf3884d1fb2234c74"),
        "measurements" : [ 
            {
                "time" : "8:00"
            }
        ],
        "measurements" : [ 
            {
                "time" : "9:00"
            }
        ]
    }],
"__v" : 0 }

请就此提出一些想法。提前致谢。

【问题讨论】:

  • 也许这个answer可以帮你找到路。
  • 谢谢,但我可以更新单个值,我的问题是我尝试根据传感器名称将多个测量(数组)值更新到传感器阵列时失败了。跨度>
  • 正如@Hayden 建议的那样,最好更改您的架构。您当前的架构实际上是无效的。对象内的键必须是唯一的。尝试在线 JSON 解析器,您会注意到错误。

标签: arrays json mongodb express mongoose


【解决方案1】:

您可能需要重新考虑您的数据模型。就目前而言,你无法完成你想要的。传感器字段是指一个阵列。在您提供的理想文档格式中,该数组中有一个对象。然后在该对象内部,您有两个具有完全相同键的字段。在 JSON 对象或此上下文中的 mongo 文档中,同一对象中不能有重复的键。

目前尚不清楚您要在这里寻找什么,但也许最好选择这样的东西:

{
"_id" : "Manasa",
"name" : "Manasa Sub",
"sensors" : [ 
    {
    "sensor_name" : "ras",
    "_id" : ObjectId("57da0a4bf3884d1fb2234c74"),
    "measurements" : [ 
        {
            "time" : "8:00"
        },
        {
            "time" : "9:00"
        }
    ]
},
{
    // next sensor in the sensors array with similar format
    "_id": "",
    "name": "",
    "measurements": []
}],
}

如果这是你想要的,那么你可以试试这个:

User.findOneAndUpdate(
    {  _id:req.body._id "sensors.sensor_name": req.body.sensor_name },
    { $push: { "sensors.0.measurements": { "time": req.body.time } } }
);

附带说明,如果您只想在测量数组的每个对象中存储一个字符串,您可能只想存储实际值而不是整个对象{ time: "value" }。您可能会发现以这种方式处理数据更容易。

【讨论】:

    【解决方案2】:

    可以使用identifier 和位置运算符$,而不是硬编码数组的索引。

    例子:

        User.findOneAndUpdate(
            {  _id: "Manasa" },
            { $push: { "sensors.$[outer].measurements": { "time": req.body.time } } }
            { "arrayFilters:" [{"outer._id": ObjectId("57da0a4bf3884d1fb2234c74")}]
        );
    

    您可能会注意到,我没有获取数组的第一个元素,而是通过提供 ObjectId 来指定要更新传感器数组的哪个元素。

    请注意,arrayFilters 作为第三个参数作为选项传递给更新查询。

    您现在可以通过传递传感器的ObjectId 使"outer._id" 动态化,如下所示:{"outer._id": req.body.sensorId}

    一般来说,使用identifier,您可以通过遵循相同的过程并添加更多过滤器来获得更深的嵌套数组元素。

    如果有第三级嵌套,您可以执行以下操作:

    User.findOneAndUpdate(
        {  _id: "Manasa" },
        { $push: { "sensors.$[outer].measurements.$[inner].example": { "time": req.body.time } } }
        { "arrayFilters:" [{"outer._id": ObjectId("57da0a4bf3884d1fb2234c74"), {"inner._id": ObjectId("57da0a4bf3884d1fb2234c74"}}]
    );
    

    您可以在 Neil Lunn 写的答案中找到更多详细信息 here

    【讨论】:

    • 谢谢!弄清楚如何使用这些标识符和位置运算符很棘手,但是您的简单示例很有帮助
    【解决方案3】:

    参考 ::: positional-all

    --- 条件 :: { other_conditions, 'array1.array2.field_to_be_checked': 'value' } --- updateData ::: { $push : { 'array1.$[].array2.$[].array3' : 'value_to_be_pushed' } }

    【讨论】:

      猜你喜欢
      • 2020-10-09
      • 2016-10-06
      • 2016-05-03
      • 2017-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-12
      相关资源
      最近更新 更多