代码之家  ›  专栏  ›  技术社区  ›  Hossein Narimani Rad

如何在PyMongo update\u many中调用另一个函数?

  •  0
  • Hossein Narimani Rad  · 技术社区  · 5 年前

    我尝试使用pyMongo向MongoDB中的文档添加另一个字段。作为一个样本,我随机从 here 我将在“已注册”部分添加另一个字段:

    from datetime import datetime
    from pymongo import MongoClient 
    
    client = MongoClient('localhost', 27017)
    db = client['metadata']
    db.users.update_many({},
    [{
        "$set":{
            "registered.newField" : "$registered.date"        
        }
    }])
    

    "$registered.date" 作为输入参数,似乎 "registered.date" 不再解析。

    db.users.update_many({},
    [{
        "$set":{    
            "registered.newField" : 
                datetime.strptime(
                  "$registered.date" ,
                  "%Y-%m-%dT%H:%M:%S.%fZ").year 
        }
    }])
    

    此抛出异常:

    '时间数据'$注册日期'与格式不匹配

    以下是文档的外观:

     {
          "gender": "male",
          "name": {
            "title": "mr",
            "first": "brad",
            "last": "gibson"
          },    
          "registered": {
            "date": "2002-05-21T10:59:49.966Z",
            "age": 17
          },
          .....
    }
    
    0 回复  |  直到 5 年前
        1
  •  1
  •   whoami - fakeFaceTrueSoul    5 年前

    db.users.update_many({},
    [{
        "$set":{    
            "registered.newField" : 
                datetime.strptime(
                  "$registered.date" ,
                  "%Y-%m-%dT%H:%M:%S.%fZ").year 
        }
    }])
    

    那么下面一行的函数:

    datetime.strptime( "$registered.date" , "%Y-%m-%dT%H:%M:%S.%fZ").year 
    

    将在应用程序服务器中执行,并在查询命中数据库之前生成结果,以便将结果更新为 "registered.newField" 现场。由于此操作是在命中DB之前进行的,因此您的查询将无法获取 "$registered.date" datetime.strptime().year 在python中 "$注册日期" 作为字符串,而不是获取字段值并进行转换。 "$注册日期"

    datetime.strptime( "2002-05-21T10:59:49.966Z" , "%Y-%m-%dT%H:%M:%S.%fZ").year 然后 .update()

    分辨率:

    当你用这个的时候 日期时间.strtime()年 为了得到一年的时间,你实际上使用了聚合操作符 $year :

    db.users.update_many({}, [
      {
        $set: {
          "registered.newField": { $year: "$registered.date" }
        }
      }
    ]);
    

    mongoplayground

    我假设你的领域 "$注册日期" 属于类型 Date ISODate('2002-05-21T10:59:49.966Z') ,如果是字符串类型,则使用 $dateFromString 转换为 &获取年份(amp;N):

    db.users.update_many({}, [
      {
        $set: {
          "registered.newField": {
            $year: {
              $dateFromString: {
                dateString: "$registered.date"
              }
            }
          }
        }
      }
    ]);
    

    测试: mongoplayground

        2
  •  1
  •   Belly Buster    5 年前

    是的,您可以在pymongo更新中绝对地调用函数;您不能做的是改变示例中的规则并依赖于 $ 运算符获取要传递到函数中的前一阶段值。

    这段代码可以工作;如果您有一个巨大的数据集,您可以用类似的方式进行批量更新。

    from pymongo import MongoClient
    import datetime
    import pprint
    
    db = MongoClient("mongodb://localhost:27019/")['mydatabase']
    
    db.users.insert_one( {
          "gender": "male",
          "name": {
            "title": "mr",
            "first": "brad",
            "last": "gibson"
          },
          "registered": {
            "date": "2002-05-21T10:59:49.966Z",
            "age": 17
          }
    })
    
    for record in db.users.find():
        try:
            date_str = record['registered']['date']
        except KeyError:
            continue
        year = datetime.datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%S.%fZ").year
        db.users.update_one({'_id': record['_id']}, {'$set': {'registered.newField': year}})
    
    pprint.pprint(db.users.find_one())