我想将一个项目推入数组并确定插入项目的索引。如何使用Mongo做到这一点?
我需要使它具有原子性,因为可以在文档上并行进行多次推送。
我正在使用Python / PyMongo作为驱动程序。
对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] }
您可以将数组的大小与数组一起存储在文档中,并在更新后获取该值:
样本输入文件:{ '_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 ] }
}
}
]