向上排列文件阵列

时间:2019-12-29 21:45:21

标签: python mongodb pymongo

我正在用Python构建MongoDB支持的API。我正在接收一系列文档以及其他一些ID。这是结构:

{
    a_id: ObjectId("..."),
    b_id: ObjectId("..."),
    all_items: [
        {item_id: ObjectId("..."), other_val: "I am other value"},
        {item_id: ObjectId("..."), other_val: "I am another value"},
        ...
    ]
}

我要做的是:根据a_id, b_id & item_id的值在一个集合中进行插入。因此,数据将按照以下方式在集合内部进行结构化:

{
    a_id: ObjectId("..."),
    b_id: ObjectId("..."),
    item_id: ObjectId("..."),
    other_val: "..."
}

因此,如果存在与a_id, b_id & item_id匹配的文档,将对其进行更新,否则将其插入。

我是否需要为每个upsert遍历整个all_items数组?请指教。

1 个答案:

答案 0 :(得分:0)

您不必遍历数组;您可以将filter()lambda expression结合使用,然后将其与其他条件结合起来:

编辑:代码示例已更新

import pymongo
from bson import ObjectId

db = pymongo.MongoClient()['mydatabase']

# Data setup
my_dict = {
    'a_id': ObjectId("111111111111111111111111"),
    'b_id': ObjectId("222222222222222222222222"),
    'all_items': [
        {'item_id': ObjectId("333333333333333333333333"), 'other_val': "I am other value"},
        {'item_id': ObjectId("444444444444444444444444"), 'other_val': "I am another value"}
    ]
}

# Filter criteria setup
a_filter = ObjectId("111111111111111111111111")
b_filter = ObjectId("222222222222222222222222")
item_filter = ObjectId("444444444444444444444444")

db.mycollection.delete_many({})

for z in filter(lambda x: x.get('item_id') == item_filter, my_dict['all_items']):
    db.mycollection.replace_one({'a_id': a_filter, 'b_id': b_filter, 'item_id': item_filter},
                                {'a_id': a_filter, 'b_id': b_filter, 'item_id': item_filter,
                                 'other_val': z.get('other_val')},
                                upsert=True)

    break  # Remove this line if you want all matching items not just the first one found

给予:

> db.mycollection.findOne({}, {'_id': 0})
{
        "a_id" : ObjectId("111111111111111111111111"),
        "b_id" : ObjectId("222222222222222222222222"),
        "item_id" : ObjectId("444444444444444444444444"),
        "other_val" : "I am another value"
}