简体   繁体   English

MongoDB | 基于一个字段逐条记录更新行

[英]MongoDB | Update rows record by record on basis of one field

I want to update the documents/records of a collection in mongodb in python with the min / max / avg of temperature on the basis of a time range.我想根据时间范围使用温度的min / max / avg更新 python 中 mongodb 中集合的文档/记录。

In the below example suppose time range is given to me "20:09-20:15", then the last row will not be updated rest of the ones will do.在下面的示例中,假设给我的时间范围是“20:09-20:15”,那么最后一行将不会更新,其余行会更新。

Sample Data:样本数据:

[
    {'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
]

Required output:所需输出:

[
    {'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
]

If you're using Mongo version 4.4+ you can use $merge to achieve this using a pipline:如果您使用的是 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蒙戈游乐场

If you're on a lesser Mongo version you have to split this into 2 calls, First use the same $group stage to fetch results, then use the values to update: (i'll write this one in python as you've tagged you're using pymongo )如果您使用的是较小的 Mongo 版本,则必须将其拆分为 2 个调用,首先使用相同的$group阶段来获取结果,然后使用这些值进行更新:你正在使用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"],
        }
    }
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM