在MongoDB中更新多个子文档数组

时间:2018-03-10 01:47:03

标签: mongodb python-3.x pymongo

我有一个完整的产品系列,每个产品都有一个最多100个产品的子文档数组(SKU):

e.g。

{
    '_id': 12345678,
    'handle': 'my-product-handle',
    'updated': false
    'variants': [
         {
              '_id': 123412341234,
              'sku': 'abc123',
              'inventory': 1
         },
         {
              '_id': 123412341235,
              'sku': 'abc124',
              'inventory': 2
         },
         ...
    ]
 }

我的目标是能够更新SKU号码的所有实例的库存数量。值得注意的是,在我正在使用的系统中,SKU 唯一。因此,如果SKU在单个产品或多个产品中多次出现,则需要将它们更新为新的库存数量。

此外,只有当该SKU的库存数量发生变化时,才需要将“已更新”字段更改为“true”*

例如,如果我想更新SKU“abc123”的所有实例以获得25个库存,则上述示例将返回此:

{
    '_id': 12345678,
    'handle': 'my-product-handle',
    'updated': true
    'variants': [
         {
              '_id': 123412341234,
              'sku': 'abc123',
              'inventory': 25
         },
         {
              '_id': 123412341235,
              'sku': 'abc124',
              'inventory': 2
         },
         ...
    ]
 }

思想?

1 个答案:

答案 0 :(得分:1)

MongoDB 3.6引入了过滤位置运算符 $[<identifier>],可用于更新数组中与数组过滤条件匹配的多个元素。您可以在此处详细了解此运算符:https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/

例如,要更新集合中每个文档的variants sku"abc123"的所有元素:

db.collection.update({}, { $set: { "variants.$[el].inventory": 25 }}, { multi: true, arrayFilters: [{ "el.sku": "abc123"}] })

不幸的是,我不知道单个查询中是否有任何方法根据文档中的其他字段是否更新来更新文档的字段。这是您必须使用一些客户端逻辑和第二个查询来实现的。

编辑(感谢Asya的评论):

您可以通过匹配将要修改的文档在单个查询中执行此操作。因此,如果nMatched和nModified必须相等,则可以将更新设置为true。例如,我认为这可以解决单个查询中的问题:

db.collection.update({ variants: { $elemMatch: { inventory: { $ne: 25 }, sku: "abc123" } } }, { $set: { "variants.$[el].inventory": 25, updated: true }}, { multi: true, arrayFilters: [{ "el.sku": "abc123"}] })

首先匹配文档,其中variants数组包含sku"abc123"inventory不等于您设置的数字的文档。然后,继续在所有匹配的子文档上设置清单,并将updated设置为true。