将聚合管道与更新操作符结合在一起

时间:2020-08-03 07:06:05

标签: mongodb

我想将不同的measurements聚合到一个充当存储桶的文档中。我收到以下格式的单个测量值:

[
  {
    "datetime": "2020-08-03T08:00:01.648475Z",
    "celsius": 20.7,
    "humidity": 57
  },
  {
    "datetime": "2020-08-03T08:05:07.756834Z",
    "celsius": 18.9,
    "humidity": 58
  }
]

聚合存储桶应如下所示:

{
  "_id": "2020-08-03",
  "celsiusHigh": 20.7,
  "celsiusLow": 18.9,
  "firstMeasurementAt": "2020-08-03T08:00:01.648475Z",
  "lastMeasurementAt": "2020-08-03T08:05:07.756834Z",
  "humidityHigh": 58,
  "humidityLow": 57,
  "measurements": [
    {
      "datetime": "2020-08-03T08:00:01.648475Z",
      "celsius": 20.7,
      "humidity": 57
    },
    {
      "datetime": "2020-08-03T08:05:07.756834Z",
      "celsius": 18.9,
      "humidity": 58
    }
  ]
}

从MongoDB 4.2开始,我可以使用Aggregation Pipelines。但是,这些管道仅支持阶段$addFields$set$project$unset$replaceRoot$replaceWith。我想使用其他更新运算符,例如$setOnInsert(仅在插入时设置一次字段),$currentDate(例如设置lastUpdatedAt)或$addToSet设置存储桶的某些字段。如果没有$addToSet,该操作将显得很冗长:

{ $set : { "measurements": { $setUnion : [ { $ifNull: [ "$measurements", [] ] } , [ { "datetime": "2020-08-03T08:05:07.756834Z", "celsius": 18.9, "humidity": 58 } ] ] } } }

是否可以将聚合管道与更新运算符结合在一起?

1 个答案:

答案 0 :(得分:1)

更新操作符一次仅支持单个对象的结构操作,因此您无法通过它们获得所需的结果。

但是您可以做的是利用$out

建立聚合管道
db.collection.aggregate([
    {
        $group: {
            _id: {$ArrayElemAt: [{$split: ["$datetime", "T"]}, 0]},
            celsiusHigh: {$max: "$celsius"},
            celsiusLow: {$min: "$celsius"},
            firstMeasurementAt: {$min: "$datetime"},
            lastMeasurementAt: {$max: "$datetime"},
            humidityHigh: {$max: "$humidity"},
            humidityLow: {$min: "$humidity"},
            measurements: {$push: "$$ROOT"}
        }
    },
    {
        $out: "collection_name"
    }
]);

请注意,这是基于所有datetimes均以相同格式/时区保存的假设。没有这个,就无法完成。