【问题标题】:Upsert timeseries in Mongodb v5 - v6在 Mongodb v5 - v6 中更新时间序列
【发布时间】:2023-02-11 14:37:36
【问题描述】:

我正在阅读有关 Mongodb v5 - v6 中时间序列的文档,但我不明白是否可以在记录保存后更新它;例如,如果我有这样的记录(“名称”字段是“元数据”):

{
  _id: ObjectId("6560a0ef02a1877734a9df66")
  timestamp: 2022-11-24T01:00:00.000Z,
  name: 'sensor1',
  pressure: 5,
  temperature: 25
}

保存记录后是否可以更新“压力”字段的值?
从官方 mongo 文档中,在“时间序列收集限制”部分中,我读到:update命令可能只修改metaField字段值.
有没有办法更新其他领域?多谢。

【问题讨论】:

    标签: mongodb time-series


    【解决方案1】:

    不,仅更新您的示例中的压力场是不可能的,并且时间序列集合不存在更新插入。

    当前可用于时间序列集合的唯一函数是删除和更新,但它们仅适用于 metaField 值,因此在您的示例中,我们只能更新/重命名“sensor1”。

    我知道更新值的唯一解决方法如下:

    1. 获取与 metaField 值匹配的所有文档的副本。
    2. 更新复制文档的所需值。
    3. 从数据库中删除原始文档
    4. 将文档的新副本插入数据库。

      这是一种使用 MongoDB Shell (mongosh) 更新时间序列集合值的方法

      首先,我们创建一个测试数据库。这里的重要部分是名为“元数据”的元字段。该字段将是一个存储多个字段的对象/字典。

      db.createCollection(
          "test_coll",
          {
             timeseries: {
                timeField: "timestamp",
                metaField: "metadata",
                granularity: "hours"
             }
          }
      )
      

      然后我们将一些测试数据添加到集合中。请注意,“元数据”是一个对象/字典,存储两个名为 传感器名称和传感器位置。

      db.test_coll.insertMany( [
          {
             "metadata": { "sensorName": "sensor1", "sensorLocation": "outside"},
             "timestamp": ISODate("2022-11-24T01:00:00.000Z"),
             "pressure": 5,
             "temperature": 32
          }, 
          {
              "metadata": { "sensorName": "sensor1", "sensorLocation": "outside" },
              "timestamp": ISODate("2022-11-24T02:00:00.000Z"),
              "pressure": 6,
              "temperature": 35
           },
           {
              "metadata": { "sensorName": "sensor2", "sensorLocation": "inside" },
              "timestamp": ISODate("2022-11-24T01:00:00.000Z"),
              "pressure": 7,
              "temperature": 72
           },
      ] )
      

      在您的示例中,我们要更新当前压力值为 5 的“压力”字段。因此,我们需要找到元字段“metadata.sensorName”的值为“sensor1”的所有文档,并存储所有找到的文档在一个名为 old_docs 的变量中。

      var old_docs = db.test_coll.find({ "metadata.sensorName": "sensor1" })
      

      接下来,我们遍历文档 (old_docs),根据需要更新它们。我们将文档(更新或未更新)添加到名为 updated_docs 的变量中。在此示例中,我们遍历所有“sensor1”文档,如果时间戳等于“2022-11-24T01:00:00.000Z”,我们将“压力”字段更新为值 555(最初为 5) .或者,我们可以在此处搜索特定的 _id 而不是特定的时间戳。

      请注意,“压力”值为 7 timestamp 2022-11-24T01:00:00.000Z,但它的值将保持不变,因为我们只是循环遍历所有“sensor1”文档,因此不会更新 sensorName 设置为 sensor2 的文档。

      var updated_docs = [];
      while (old_docs.hasNext()) {
          var doc = old_docs.next();
          if (doc.timestamp.getTime() == ISODate("2022-11-24T01:00:00.000Z").getTime()){
              print(doc.pressure)
              doc.pressure = 555
          }
          updated_docs.push(doc)
      }
      

      我们现在拥有“sensor1”的所有文档的副本,并且我们已经更新了所需的字段。

      接下来,我们删除元字段'metadata.sensorName'等于'sensor1'的所有文档(在实际数据库中,请不要忘记先备份)

      db.test_coll.deleteMany({ "metadata.sensorName": "sensor1" })
      

      最后,我们将更新后的文档插入数据库。

      db.test_coll.insertMany(updated_docs)
      

      此解决方法将更新值,但不会更新它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-17
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      • 2017-01-22
      • 2011-09-05
      • 1970-01-01
      • 2015-10-11
      相关资源
      最近更新 更多