Python MongoDB中的位置更新
我正在尝试更新MongoDB中的一系列子文档。我知道位置运算符Python MongoDB中的位置更新,python,mongodb,pymongo,Python,Mongodb,Pymongo,我正在尝试更新MongoDB中的一系列子文档。我知道位置运算符$不支持单个查询中的多个更新 样本文件: { "_id": ObjectId("559a6c281816ba598cdf96cd"), "collections": [ { "id": 12, "name": "a" }, { "id": 12, "name": "b" } ] } 我需要用一个额外的字段更新id:12子文档“price”:1
$
不支持单个查询中的多个更新
样本文件:
{
"_id": ObjectId("559a6c281816ba598cdf96cd"),
"collections": [
{
"id": 12,
"name": "a"
},
{
"id": 12,
"name": "b"
}
]
}
我需要用一个额外的字段更新id:12
子文档“price”:12
。我尝试了以下查询,但匹配的同一子文档正在更新,因此我添加了一个额外条件“price”:{$exists:false}
,并尝试了“price”:{$ne:12}
。当我添加“price”:{$exists:false}
没有返回任何文档。我正在使用PyMongo和python。因此,我需要在python代码中执行更新并更新文档。有什么解决办法吗
已尝试的查询:
db.scratch.update({ "collections.id" : 12 } , {"$set" : {"collections.$.price" : 12 }})
使用上面的price:false
,price:{$exists:false}
组合进行了尝试,但它们也不起作用。但我不断收到一条信息,即一份文档已更新。我在我的mongo shell中使用mongo hacker
我正在构建一个迁移工具,其中所有客户信息都作为单个文档呈现
{
"_id": ObjectId("559a2d9bfffe043444c72889"),
"age": NumberLong("23"),
"customer_address": [
{
"type": "Work",
"verified": true,
"address": "1A NY"
}
],
"customer_id": NumberLong("3"),
"customer_orders": [
{
"order_date": ISODate("2015-01-01T00:12:01Z"),
"order_id": NumberLong("2"),
"product_id": NumberLong("234")
},
{
"order_date": ISODate("2015-12-01T00:00:00Z"),
"order_id": NumberLong("3"),
"product_id": NumberLong("245")
},
{
"order_date": ISODate("2015-12-21T00:00:00Z"),
"order_id": NumberLong("4"),
"product_id": NumberLong("267")
},
{
"order_id": NumberLong("5"),
"order_date": ISODate("2015-12-29T00:00:00Z"),
"product_id": NumberLong("289")
},
{
"order_id": NumberLong("9"),
"order_date": ISODate("2015-02-01T00:12:05Z"),
"product_id": NumberLong("234")
}
]
}
我从客户表中获取基本信息,从客户地址表中获取地址,从MySQL中外键引用相关的另一个表中获取产品日志。现在我想用正确的名称和价格更新产品id,这样我就可以查看客户,而不是通过查询来获取产品id的相应价格,而且因为join在中不存在
{
"_id": ObjectId("559a2d9bfffe043444c72889"),
"age": NumberLong("23"),
"customer_address": [
{
"type": "Work",
"verified": true,
"address": "1A NY"
}
],
"customer_id": NumberLong("3"),
"customer_orders": [
{
"name": "Brush",
"order_date": ISODate("2015-01-01T00:12:01Z"),
"order_id": NumberLong("2"),
"product_id": NumberLong("234"),
"price": 12
},
{
"order_date": ISODate("2015-12-01T00:00:00Z"),
"order_id": NumberLong("3"),
"product_id": NumberLong("245")
},
{
"order_date": ISODate("2015-12-21T00:00:00Z"),
"order_id": NumberLong("4"),
"product_id": NumberLong("267")
},
{
"order_id": NumberLong("5"),
"order_date": ISODate("2015-12-29T00:00:00Z"),
"product_id": NumberLong("289")
},
{
"name": "Brush",
"order_id": NumberLong("9"),
"order_date": ISODate("2015-02-01T00:12:05Z"),
"product_id": NumberLong("234"),
"price": 12
}
]
}
尝试过的查询:
db.customer.update({"customer_orders.product_id" : 234 , "customer_orders.name" : {$exists : false}}, {"$set" : {"customer_orders.$.name" : "Brush", "customer_orders.$.price" : 12} } )
返回0个已更新的文档
db.customer.update({"customer_orders.product_id" : 234 , "customer_orders.name" : {$exists : true}}, {"$set" : {"customer_orders.$.name" : "Brush", "customer_orders.$.price" : 12} } )
返回1个已更新的文档,但即使在连续执行同一命令后,也只更新第一个字段。那么,有什么解决方法吗?或者我需要在Python客户端中进行更新吗?除了阅读文档以找出有多少数组元素并按索引(或不同的“id”值)进行更新之外,这真的没什么大不了的,但首先阅读对象并不重要 以最安全的方式,不要更改整个文档并将其“保存”回去,而是对每个数组元素执行更新:
id=ObjectId(“559a2d9bfffe043444c72889”)
doc=coll.find_one({“\u id”:id})
对于idx,枚举中的el(文档[“客户订单]):
如果(el[“产品标识”]==234):
更新={“$set”:{}
更新[“$set”][“客户订单”+str(idx)+“.price”]=12
更新[“$set”][“客户订单”+str(idx)+“.name”]=“刷子”
coll.update({“\u id”:id},update)
通过批量操作,您可以提高效率:
id=ObjectId(“559a2d9bfffe043444c72889”)
doc=coll.find_one({“\u id”:id})
bulk=coll.initialize\u ordered\u bulk\u op()
对于idx,枚举中的el(文档[“客户订单]):
如果(el[“产品标识”]==234):
更新={“$set”:{}
更新[“$set”][“客户订单”+str(idx)+“.price”]=12
更新[“$set”][“客户订单”+str(idx)+“.name”]=“刷子”
bulk.find({“\u id”:id}).update(更新)
bulk.execute()
至少一次将所有更新发送到服务器
但一般的过程是,为了发送正确的更新位置,您需要通过其他唯一标识符的索引来识别“精确”元素
试着像
{“客户订单.价格”:{“$exists”:False}
或
{“客户订单.产品id”:234}
将遇到以下问题:
- 总之,在这两种情况下,它都会匹配多个内容
- 对于
,对于位置$exists
匹配操作是不可接受的,只有精确的值匹配才会生成用于更新的索引$
因此,请从文档本身中读取“精确”id或位置索引,然后处理更新。您的问题不是以“我知道位置运算符不支持单个查询中的多个更新”开始的吗?因此,由于两个子文档具有相同的“id”那么您还希望发生什么呢?不要假设您使用了
“collections.price”:{“$exists”:false}
因为这是元素的路径。@BlakesSeven我认为可以使用相同的条件重复更新,即在多个查询中进行多次更新。当我有许多相同id的文档要更新时,我将使用确切的场景更新问题。请按照“$exists:false”这样做无法匹配元素。如果所有项都具有相同的“id”,则它只会匹配第一个。不同的“id”值当然是另一种情况。在这个场景中,它应该是product_id
,我想在这里插入一些product_id
的信息,我在前面的注释中提到了id
。我的错。添加了这个场景。@BlakesSeven