【问题标题】:$push and $set in same update query with condition $cond pymongo mongodb$push 和 $set 在同一个更新查询中,条件为 $cond pymongo mongodb
【发布时间】:2020-08-23 15:20:19
【问题描述】:

我正在尝试更新我的收藏

对于单,对象需要更新状态和更新时间。

输入对象ID为id新状态为当前status

条件如果new status与DB中的status不同,则需要将$pushnew statustimestamp放入activity_log数组中。 并更新更新记录的updated_timestatus

如果new status 和之前的状态相同,那么updated_time 将被更新。

是否可以在 pymongo 中使用单次更新来做到这一点?

collection.update({
        '_id': ObjectId(id),
    }, {
        '$cond': {
            'if': {
                'status': {
                    '$ne': current_status
                }
            },
            'then': {
                '$push': {
                    'activity_log': {
                        'status': current_status,
                        'changed_time': datetime.now()
                    }
                }
            },
            'else': None
        },
        '$set': {
            'status': current_status,
            'updated_time': datetime.now()
        }
    })

【问题讨论】:

  • 请使用 1) 示例文档、2) 输入、3) 要应用的条件和 4) 应用更新后的结果文档来编辑此问题!数据库版本?
  • 更新了输入和条件mongodb版本为MongoDB 4.2.5 Community
  • 我已经更新了我的答案,可以在单个查询中完成,我已经在 Mongo 客户端上尝试过更新的查询正在运行,请检查。

标签: python mongodb nosql pymongo mongodb-update


【解决方案1】:

您可以在单个查询中执行此操作,从 MongoDB 4.2 更新查询支持aggregation pipeline,您可以按照以下代码执行此操作

collection.update(
     {'_id': ObjectId(id)}, 
     [{'$set': {
            'status': current_status,
            'updated_time': datetime.now(),
            'activity_log':{
              '$cond': {
                'if': {'$ne': ['$status',current_status]},
                'then': {$concatArrays:['$activity_log',[
                          {
                           'status': current_status,
                           'changed_time': datetime.now()
                          }
                ]]},
                'else': '$activity_log'
            }
      }}}]
)

【讨论】:

    【解决方案2】:

    $cond 运算符不是像 if-then-else 那样的流控制,它是一个返回值的表达式。

    如果要根据同一文档中另一个字段的值有条件地更新一个字段,可以使用更新的管道形式,将$cond表达式的结果分配给该字段。

    collection.update(
         {'_id': ObjectId(id)}, 
         [{'$set': {
                'status': current_status,
                'updated_time': datetime.now(),
                'activity_log':{
                  '$cond': {
                    'if': {'$ne': ['$status',current_status]}
                    'then': {$concatArrays:['$activity_log',[
                              {
                               'status': current_status,
                               'changed_time': datetime.now()
                              }
                    ]]},
                    'else': '$activity_log'
                }
          }}]
    )
    

    【讨论】:

    • 我认为上面的方式是正确的pymongo正在触发in validate_is_mapping raise TypeError("%s must be an instance of dict, bson.son.SON, or " TypeError: document must be an instance of dict, bson.son.SON, or any other type that inherits from collections.Mapping
    • MongoDB 4.2 中添加的管道更新形式。如果您使用的 pymongo 版本不支持 update 函数,您可以使用 db.command 运行 update 数据库命令
    猜你喜欢
    • 2012-02-22
    • 2018-05-28
    • 1970-01-01
    • 2016-09-22
    • 2021-04-25
    • 2017-10-23
    • 2016-05-30
    • 2014-06-27
    • 1970-01-01
    相关资源
    最近更新 更多