如何将项目推入数组并在MongoDB中获得该项目的索引,在find_one_and_update pymongo中投影

问题描述 投票:1回答:2

我想将一个项目推入数组并确定插入项目的索引。如何使用Mongo做到这一点?

我需要使它具有原子性,因为可以在文档上并行进行多次推送。

我正在使用Python / PyMongo作为驱动程序。

python mongodb mongodb-query pymongo
2个回答
0
投票

对MongoDB中单个文档的更新为atomic,因此,如果一个更新操作正在写入文档,则以下更新操作必须等到第一个更新完成。因此,您可以返回更新的文档,并在代码中获取新推入值的索引(因为$push通常将推入数组的末尾)。

因此,当您使用MongoDB的聚合框架进行读取时-您可以在$indexOfArray阶段使用$project运算符来获取数组中元素的索引。但是投影是聚合框架比.find().findOneAndUpdate()的投影可以接受更多的运算符。使用更新操作可能无法获取数组中元素的索引,因此使用以下查询可以从更新的文档返回完整的新数组,并使用python尝试获取新数组中元素的索引。

样本文档:

{
  _id: ObjectId("5eb773b8c4ec53c0626b167e"),
  name: "YesMe",
  ids: [1, 2, 3],
};

查询:

db.collection.find_one_and_update(
  { name: "YesMe" },
  { $push: { ids: 4 } },
  (projection = { ids: True, _id: False }), // Projecting only `ids` field
  (return_document = ReturnDocument.AFTER) // Returns updated doc (In your case updated array)
);

输出:

{ ids : [1, 2, 3, 4] }

Ref: Collection.find_one_and_update


0
投票

您可以将数组的大小与数组一起存储在文档中,并在更新后获取该值:

样本输入文件:{ '_id: 1', 'arr': [ "apple", "orange" ] }

更新操作-对更新使用管道(可用于MongoDB 4.2版):

NEW_ITEM = 'pear'

r = collection.find_one_and_update(
  { '_id': 1 },
  [
    { 
      '$set': { 
        'ix': { '$size': '$arr' }, 
        'arr': { '$concatArrays': [ '$arr', [ NEW_ITEM ] ] } 
      } 
    }
  ],
  projection = { '_id': False, 'ix': True }, 
  return_document = ReturnDocument.AFTER
)

另一种方法是在同一更新操作中设置新插入元素的索引(如果数组元素是唯一的,则可以使用此方法:]

  [
    { 
      '$set': { 
        'arr': { '$concatArrays': [ '$arr', [ NEW_ITEM ] ] } 
      },
      '$set': { 
        'ix': { '$indexOfArray': [ '$arr', NEW_ITEM ] } 
      }
    }
  ]
© www.soinside.com 2019 - 2024. All rights reserved.