Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python MongoDB中的位置更新_Python_Mongodb_Pymongo - Fatal编程技术网

Python 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

我正在尝试更新MongoDB中的一系列子文档。我知道位置运算符
$
不支持单个查询中的多个更新

样本文件:

{
  "_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