【问题标题】:MongoDB | Update rows record by record on basis of one fieldMongoDB |根据一个字段逐记录更新行
【发布时间】:2021-01-17 08:36:35
【问题描述】:

我想根据时间范围用温度的min/max/avg 更新python中mongodb中集合的文档/记录。

在下面的示例中,假设给我的时间范围是“20:09-20:15”,那么最后一行将不会更新,其余行会更新。

样本数据:

[
    {'date': "1-10-2020", 'time': "20:09", 'temperature': 20}, //1
    {'date': "1-10-2020", 'time': "20:11", 'temperature': 19}, //2 
    {'date': "1-10-2020", 'time': "20:15", 'temperature': 18}, //3
    {'date': "1-10-2020", 'time': "20:18", 'temperature': 18} //4
]

需要的输出:

[
    {'date': "1-10-2020", 'time': "20:09", 'temperature': 20, 'MIN': 20, 'MAX': 20, 'AVG': 20}, //1
    {'date': "1-10-2020", 'time': "20:11", 'temperature': 19, 'MIN': 19, 'MAX': 20, 'AVG': 19.5}, //2
    {'date': "1-10-2020", 'time': "20:15", 'temperature': 18, 'MIN': 18, 'MAX': 20, 'AVG': 19}, //3
    {'date': "1-10-2020", 'time': "20:18", 'temperature': 18} //4
]

【问题讨论】:

    标签: python python-3.x mongodb pymongo pymongo-2.x


    【解决方案1】:

    如果您使用的是 Mongo 4.4+ 版,您可以使用 $merge 来通过管道实现此目的:

    db.collection.aggregate([
      {
        $match: {
          time: {
            $gte: "20:09",
            $lte: "20:15"
          }
        }
      },
      {
        $group: {
          _id: null,
          avg: {
            $avg: "$temperature"
          },
          min: {
            $min: "$temperature"
          },
          max: {
            $max: "$temperature"
          },
          root: {
            $push: "$$ROOT"
          }
        }
      },
      {
        $unwind: "$root"
      },
      {
        "$replaceRoot": {
          "newRoot": {
            "$mergeObjects": [
              "$root",
              {
                "MIN": "$min",
                "MAX": "$max",
                "AVG": "$avg"
              }
            ]
          }
        }
      },
      {
        $merge: {
          into: "collection",
          on: "_id",
          whenMatched: "replace"
        }
      }
    ])
    

    Mongo Playground

    如果您使用的是较小的 Mongo 版本,则必须将其拆分为 2 个调用,首先使用相同的 $group 阶段来获取结果,然后使用值进行更新:(我将在 python 中编写这个为你已经标记了你正在使用pymongo)

    results = list(collection.aggregate([
        {
            "$match": {
                "time": {
                    "$gte": "20:09",
                    "$lte": "20:15"
                }
            }
        },
        {
            "$group": {
                "_id": None,
                "avg": {
                    "$avg": "$temperature"
                },
                "min": {
                    "$min": "$temperature"
                },
                "max": {
                    "$max": "$temperature"
                },
                "root": {
                    "$push": "$$ROOT"
                }
            }
        }
    ]))
    
    collection.update_many(
        {
            "time": {
                "$gte": "20:09",
                "$lt": "20:15"
            }
        },
        {
            "$set": {
                "MAX": results[0]["max"],
                "MIN": results[0]["min"],
                "AVG": results[0]["avg"],
            }
        }
    )
    

    【讨论】:

    • 您好,感谢您的回复,但它会更新所有具有 max/min/value 正确的行(所有 4 行的 bascally 组合结果)?我想逐行更新行,就像第一条记录是自身的温度值,然后第二条记录是第一行和第二行的结果,依此类推..
    猜你喜欢
    • 2016-09-13
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多