更新嵌套数组Mongoose

Inq*_*irl 6 arrays json mongoose mongodb 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}]
}] });
Run Code Online (Sandbox Code Playgroud)

2)这是代码片段,解释如下:

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)
}); });
Run Code Online (Sandbox Code Playgroud)

我能够使用带推技术的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"
    }
  ]
  }]} 
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

正确的JSON格式是:

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

请提出一些有关此问题的建议.提前致谢.

Hay*_*ton 10

您可能想重新考虑数据模型.就目前而言,你无法达到你想要的效果.传感器字段指的是数组.在您提供的理想文档格式中,该数组中有一个对象.然后在该对象内部,您有两个具有完全相同键的字段.在此上下文中的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": []
}],
}
Run Code Online (Sandbox Code Playgroud)

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

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

作为旁注,如果您只想在测量数组中的每个对象中存储单个字符串,您可能只想存储实际值而不是整个对象{ time: "value" }.您可能会发现这种方式更容易处理数据.

希望这可以帮助.


Jak*_*cki 8

可以使用标识符和位置运算符$代替对数组的索引进行硬编码。

例子:

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

您可能会注意到,我没有通过提供它的ObjectId.

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

您现在可以"outer._id"通过ObjectId像这样传递传感器的 来实现动态:{"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"}}]
);
Run Code Online (Sandbox Code Playgroud)

你可以找到更多的细节在这里由尼尔·伦恩书面答复。