使用 $set 和 $avg、max、min 更新我的 mongo collection 上的字段

Update a field on my mongo collection with $set and $avg, max, min

我的 mongo collection 文件中有:

{
    "_id": {
        "date": "2046-12-17",
        "device": "782330b8f41-8980-4b81-9e04-d7c08a9d621e"
    },
    "organizationId": 7,
    "smartSpaceId": 82,
    "typeName": "sensor",
    "typeId": 12,
    "smartDeviceId": "330b8f41-8980-4b81-9e04-d7c08a9d621e",
    "isVirtual": false,
    "receivedTopic": "spot-pre.7.82.data",
    "samples": [
        {
            "t": 2428626587,
            "tS": 2428626640,
            "tR": 2428626631,
            "value": {
                "measure": 4.77799988,
                "time": 161304136258,
                "meta": {
                    "is_reachable": true
                }
            }
        },
        {
            "t": 2428627687,
            "tS": 2428627840,
            "tR": 2428627731,
            "value": {
                "measure": 7.7234234988,
                "time": 161304146358,
                "meta": {
                    "is_reachable": true
                }
            }
        },
        {
            "t": 2428626997,
            "tS": 2428624570,
            "tR": 2428226631,
            "value": {
                "measure": 12.74352588,
                "time": 161304132348,
                "meta": {
                    "is_reachable": true
                }
            }
        },
        {
            "t": 2428626587,
            "tS": 2428626587,
            "tR": 2428626587,
            "value": {
                "measure": 20.01,
                "time": 161304136368,
                "meta": {
                    "is_reachable": true
                }
            }
        }
    ],
    "nsamples": 4,
    "stats_value_measure": {
        "avg": 8.414983086266667,
        "min": 4.77799988,
        "max": 12.74352588,
        "sum": 45.254949258799999
    }
}

我正在尝试执行此查询以更新提交的平均值、最大值和最小值:

db.deviceMeasure.updateOne(
{ 
    "_id": {
        "date": "2020-12-17",
        "device": "782330b8f41-8980-4b81-9e04-d7c08a9d621e"
    } 
},
{ 
    "$push": { 
        "samples": {
            "t": 2428626587,
            "tS": 2428626587,
            "tR": 2428626587,
            "value": { 
                "measure": 25.01, 
                "time": 161304136368, 
                "meta": { 
                    "is_reachable": true 
                } 
            }
        } 
    },
    "$inc": { "nsamples": 1, "stats_value_measure.sum": 20.01 },
    "$set": { 
        "stats_value_measure": {
            "avg": { $avg: "samples.value.measure" },
            "min": { $min: "samples.value.measure" },
            "max": { $max: "samples.value.measure" },
            "sum": { $sum: "samples.value.measure" }
    }
},
{ upsert: true })

但在我的 shell 中我只看到“...” 你能帮帮我吗?

对于 Mongo v4.2+,您可以使用 pipelined updates,这允许我们在更新中使用文档字段值。您只需调整运算符以使用聚合运算符而不是更新运算符,如下所示:

db.deviceMeasure.updateOne(
{ 
    "_id": {
        "date": "2020-12-17",
        "device": "782330b8f41-8980-4b81-9e04-d7c08a9d621e"
    } 
},
[
  {
    "$set": {
      "samples": {
        $concatArrays: [
          "$samples",
          [
            {
              "t": 2428626587,
              "tS": 2428626587,
              "tR": 2428626587,
              "value": {
                "measure": 25.01,
                "time": 161304136368,
                "meta": {
                  "is_reachable": true
                }
              }
            }
          ]
        ]
      },
      nsamples: {
        $sum: [
          1,
          "$nsamples"
        ]
      },
      "stats_value_measure.sum": {
        $sum: [
          "stats_value_measure.sum",
          20.01
        ]
      }
    }
  },
  {
    "$set": {
      "stats_value_measure": {
        "avg": {
          $avg: "$samples.value.measure"
        },
        "min": {
          $min: "$samples.value.measure"
        },
        "max": {
          $max: "$samples.value.measure"
        },
        "sum": {
          $sum: "$samples.value.measure"
        }
      }
    }
  }
])

Mongo Playground

对于较小的 Mongo 版本,您必须将文档读入内存并在代码中进行计算,因为您不能在更新中使用文档字段值。