Python MongoDB使用$cond进行更新($inc)

Python MongoDB使用$cond进行更新($inc),python,mongodb,pymongo,mongodb-update,Python,Mongodb,Pymongo,Mongodb Update,有没有办法在更新中使用$cond和($set,$inc,…)操作符?(MongoDB 4.2) 如果条件变为现实,我想用$inc将文档中的字段更新为“myDataInt”,否则保持原样: db.mycoll.update( {"_id" : "5e9e5da03da783817d231dc4"}, {"$inc" : { "my_data_sum" : { "$cond" : [ {

有没有办法在更新中使用$cond和($set,$inc,…)操作符?(MongoDB 4.2) 如果条件变为现实,我想用$inc将文档中的字段更新为“myDataInt”,否则保持原样:

db.mycoll.update(
    {"_id" : "5e9e5da03da783817d231dc4"},
    {"$inc" : {
       "my_data_sum" : {
           "$cond" : [
               {
                  "$ne" : ["snapshot_time", new_snapshot_time)]
               },myDataInt, 0]
           ]
       }
    },
    {upsert=True, multi=False}
)
但是,这在pymongo中给出了一个错误:

raise WriteError(error.get("errmsg"), error.get("code"), error)
pymongo.errors.WriteError: The dollar ($) prefixed field '$cond' in 'my_data_sum.$cond' is not valid for storage.
在这种情况下,有没有办法避免在更新之前使用find()


更新:

如果我使用Joe提到的方法,PyMongo(v3.10.1)中会出现一个异常,因为在update_many()中使用'list'作为参数,而不是'dict':

from pymongo import MongoClient

db = MongoClient()['mydb']

db.mycoll.update_many(
    {"_id" : "5e9e5da03da783817d231dc4"},
    [{"$set" : {
       "my_data_sum" : {
           "$sum": [
               "$my_data_sum",
               {"$cond" : [
                   {"$ne" : ["snapshot_time", new_snapshot_time]},
                   myDataInt, 
                   0
               ]}
           ]
       }
    }}],

    upsert:true
)

这将导致以下错误:

  File "/usr/local/lib64/python3.6/site-packages/pymongo/collection.py", line 1076, in update_many session=session),
  File "/usr/local/lib64/python3.6/site-packages/pymongo/collection.py", line 856, in _update_retryable _update, session)
  File "/usr/local/lib64/python3.6/site-packages/pymongo/mongo_client.py", line 1491, in _retryable_write return self._retry_with_session(retryable, func, s, None)
  File "/usr/local/lib64/python3.6/site-packages/pymongo/mongo_client.py", line 1384, in _retry_with_session return func(session, sock_info, retryable)
  File "/usr/local/lib64/python3.6/site-packages/pymongo/collection.py", line 852, in _update retryable_write=retryable_write)
  File "/usr/local/lib64/python3.6/site-packages/pymongo/collection.py", line 823, in _update _check_write_command_response(result)
  File "/usr/local/lib64/python3.6/site-packages/pymongo/helpers.py", line 221, in _check_write_command_response _raise_last_write_error(write_errors)
  File "/usr/local/lib64/python3.6/site-packages/pymongo/helpers.py", line 203, in _raise_last_write_error raise WriteError(error.get("errmsg"), error.get("code"), error)
pymongo.errors.WriteError: Modifiers operate on fields but we found type array instead. For example: {$mod: {<field>: ...}} not {$set: [ { $set: { my_data_sum: { $sum: [ "$my_data_sum", { $cond: [ { $ne: [ "$snapshot_time", 1586910283 ] }, 1073741824, 0 ] } ] } } } ]}
File“/usr/local/lib64/python3.6/site packages/pymongo/collection.py”,第1076行,在update_many session=session中,
文件“/usr/local/lib64/python3.6/site packages/pymongo/collection.py”,第856行,在会话更新中
文件“/usr/local/lib64/python3.6/site packages/pymongo/mongo_client.py”,第1491行,在可重试的写返回self中
文件“/usr/local/lib64/python3.6/site packages/pymongo/mongo_client.py”,第1384行,在带有会话返回函数的“重试”中(会话,sock_信息,可重试)
文件“/usr/local/lib64/python3.6/site packages/pymongo/collection.py”,第852行,在_updateretryable\u write=retryable\u write中)
文件“/usr/local/lib64/python3.6/site packages/pymongo/collection.py”,第823行,在“更新”、“检查”、“写入”命令响应(结果)中
文件“/usr/local/lib64/python3.6/site packages/pymongo/helpers.py”,第221行,检查写入命令响应最后写入错误(写入错误)
文件“/usr/local/lib64/python3.6/site packages/pymongo/helpers.py”,第203行,在“raise\u last\u write\u error raise WriteError(error.get(“errmsg”)、error.get(“code”)、error中
pymongo.errors.WriteError:修饰符对字段进行操作,但我们找到了类型数组。例如:{$mod:{:…}}不是{$set:{$set:{my_data_sum:{$sum:[“$my_data_sum”,{$cond:[{$ne:[“$snapshot_time”,1586910283]},1073741824,0]}}

如果您使用的是MongoDB 4.2,则可以在更新时使用聚合运算符
$inc
不是聚合运算符,但
$sum
是。要指定管道,请将数组作为第二个参数传递给
update

db.coll.update(
    {"_id" : "5e9e5da03da783817d231dc4"},
    [{"$set" : {
       "my_data_sum" : {
           "$sum": [
               "$my_data_sum",
               {"$cond" : [
                   {"$ne" : ["snapshot_time", new_snapshot_time]},
                   myDataInt, 
                   0
               ]}
           ]
       }
    }}],
    {upsert:true, multi:false}
)

如果您使用的是MongoDB 4.2,则可以在更新时使用聚合运算符
$inc
不是聚合运算符,但
$sum
是。要指定管道,请将数组作为第二个参数传递给
update

db.coll.update(
    {"_id" : "5e9e5da03da783817d231dc4"},
    [{"$set" : {
       "my_data_sum" : {
           "$sum": [
               "$my_data_sum",
               {"$cond" : [
                   {"$ne" : ["snapshot_time", new_snapshot_time]},
                   myDataInt, 
                   0
               ]}
           ]
       }
    }}],
    {upsert:true, multi:false}
)

在花了一些时间在线搜索之后,我发现PyMongo中收集对象的
update\u many()
update\u one()
update()
方法不接受类型列表作为参数来支持MongoDB 4.2+中更新操作的新聚合管道功能。(至少这个选项在PyMongo v3.10中还不可用。)

但是,看起来我可以使用PyMongo中数据库对象的
命令
方法,它是()的一个实例,对我来说效果很好:

from pymongo import MongoClient

db = MongoClient()['mydb']

result = db.command(
    {
        "update" : "mycoll",
        "updates" : [{
            "q" : {"_id" : "5e9e5da03da783817d231dc4"},
            "u" : [
                {"$set" : {
                   "my_data_sum" : {
                       "$sum": [
                           "$my_data_sum",
                           {"$cond" : [
                               {"$ne" : ["snapshot_time", new_snapshot_time]},
                               myDataInt,
                               0
                           ]}
                       ]
                   }
                }}
            ],
            "upsert" : True,
            "multi" : True
        }],
        "ordered": False
    }
)
数据库对象的
command
方法获取所有必需命令的dict对象作为其第一个参数,然后聚合管道列表可以包含在dict对象中(
q
是更新查询,
u
定义了要更新的字段)


result
是一个来自MongoDB的Ack消息字典,其中包含'nmodied''upserted'、和'writeErrors'

在花费一些时间和在线搜索之后,我发现
更新了很多()
更新了一个()
,以及
更新()
PyMongo中收集对象的方法不接受类型列表作为参数,以支持MongoDB 4.2+中更新操作的新聚合管道功能。(至少这个选项在PyMongo v3.10中还不可用。)

但是,看起来我可以使用PyMongo中数据库对象的
命令
方法,它是()的一个实例,对我来说效果很好:

from pymongo import MongoClient

db = MongoClient()['mydb']

result = db.command(
    {
        "update" : "mycoll",
        "updates" : [{
            "q" : {"_id" : "5e9e5da03da783817d231dc4"},
            "u" : [
                {"$set" : {
                   "my_data_sum" : {
                       "$sum": [
                           "$my_data_sum",
                           {"$cond" : [
                               {"$ne" : ["snapshot_time", new_snapshot_time]},
                               myDataInt,
                               0
                           ]}
                       ]
                   }
                }}
            ],
            "upsert" : True,
            "multi" : True
        }],
        "ordered": False
    }
)
数据库对象的
command
方法获取所有必需命令的dict对象作为其第一个参数,然后聚合管道列表可以包含在dict对象中(
q
是更新查询,
u
定义了要更新的字段)


result
是来自MongoDB的Ack消息字典,其中包含'nModified''upserted''writeErrors'

我试图采用相同的方法,但pymongo似乎不接受“list”作为“update”和“update\u many”的第二个参数。它只接受dict类型!有什么想法吗?(使用pymongo 3.10)根据
update\u one
update\u many
接受从版本3.9开始的管道。您正在运行哪个版本的MongoDB?我正在运行MongoDB 4.2和PyMongo 3.10.1。我可以在MongoDB中毫无问题地运行此更新。但是PyMongo不接受列表类型作为update\u one或update\u many参数,并给出了以下错误:
TypeError:document必须是dict的一个实例,bson.son.son,或者从集合继承的任何其他类型。Mapping
您可以将新的python代码编辑到问题中,以便我们可以尝试它吗?我尝试使用相同的方法,但pymongo似乎不接受“list”作为“update”和“update\u many”的第二个参数。它只接受dict类型!有什么想法吗?(使用pymongo 3.10)根据
update\u one
update\u many
接受从版本3.9开始的管道。您正在运行哪个版本的MongoDB?我正在运行MongoDB 4.2和PyMongo 3.10.1。我可以在MongoDB中毫无问题地运行此更新。但是PyMongo不接受list type作为update\u one或update\u many参数,并给出了以下错误:
TypeError:document必须是dict的实例,bson.son.son,o