Python 使用'进行批量插入$addToSet';要添加一组对象,请创建嵌套的字典数组,而不是字典数组

Python 使用'进行批量插入$addToSet';要添加一组对象,请创建嵌套的字典数组,而不是字典数组,python,mongodb,pymongo,Python,Mongodb,Pymongo,我正在尝试使用PyMongo将数据批量上传到mongoDB 我的目标如下: 检查数据库中是否存在工作应用程序id 如果存在,将“tobeaded”数组中的唯一对象与mongoDB中的相应字段连接起来 如果它不存在,则创建一个“appl_id”为“working_appl_id”的记录,并设置“tobeaded”字典 例如。 将以下内容插入空数据库 Appl Id | First Name | Last Name | Ip Address | Ip Country 123 |

我正在尝试使用PyMongo将数据批量上传到mongoDB

我的目标如下:

  • 检查数据库中是否存在工作应用程序id
  • 如果存在,将“tobeaded”数组中的唯一对象与mongoDB中的相应字段连接起来
  • 如果它不存在,则创建一个“appl_id”为“working_appl_id”的记录,并设置“tobeaded”字典
  • 例如。 将以下内容插入空数据库

        Appl Id | First Name | Last Name | Ip Address | Ip Country  
        123 | John | Johnson | x.x.x.x | USA
        123 | Peter | Peterson | y.y.y.y | FRA
    
    应该导致

    {
        'appl_id': 123,
        'name':[
            {'first':'John', 'last':'Johnson'}, 
            {'first':'Peter', 'last':'Peterson'}
        ],
        'ip':[
            {'address': 'x.x.x.x', 'country': 'USA'},
            {'address': 'y.y.y.y', 'country': 'FRA'}
        ]
    },
    
    {
        'appl_id': 123,
        'name':[
            {'first':'John', 'last':'Johnson'}, 
            {'first':'Peter', 'last':'Peterson'}, 
            {'first':'Mayer', 'last':'Mayerson'}
        ],
        'ip':[
            {'address': 'x.x.x.x', 'country': 'USA'},
            {'address': 'y.y.y.y', 'country': 'FRA'},
            {'address': 'z.z.z.z', 'country': 'GER'}
        ]
    },
    {
        'appl_id': 456,
        'name': [
            {'first':'Will', 'last':'Willson'},
        ],
        'ip': [
            {'address': 'x.x.x.x', 'country': 'USA'}
        ]
    },
    
    现在将以下内容添加到上述数据库中

        Appl Id | First Name | Last Name | Ip Address | Ip Country  
        123 | Mayer | Mayerson | x.x.x.x | USA
        123 | John | Johnson | z.z.z.z | GER
        456 | Will | Willson | x.x.x.x | USA
    
    应该导致

    {
        'appl_id': 123,
        'name':[
            {'first':'John', 'last':'Johnson'}, 
            {'first':'Peter', 'last':'Peterson'}
        ],
        'ip':[
            {'address': 'x.x.x.x', 'country': 'USA'},
            {'address': 'y.y.y.y', 'country': 'FRA'}
        ]
    },
    
    {
        'appl_id': 123,
        'name':[
            {'first':'John', 'last':'Johnson'}, 
            {'first':'Peter', 'last':'Peterson'}, 
            {'first':'Mayer', 'last':'Mayerson'}
        ],
        'ip':[
            {'address': 'x.x.x.x', 'country': 'USA'},
            {'address': 'y.y.y.y', 'country': 'FRA'},
            {'address': 'z.z.z.z', 'country': 'GER'}
        ]
    },
    {
        'appl_id': 456,
        'name': [
            {'first':'Will', 'last':'Willson'},
        ],
        'ip': [
            {'address': 'x.x.x.x', 'country': 'USA'}
        ]
    },
    
    我的代码如下所示

    db = client['some_db']
    col = db['some_collection']
    bulk = col.initialize_unordered_bulk_op()
    
    working_appl_id=123
    toBeAdded={
        "name":[
            {'first':'John', 'last':'Johnson'}, 
            {'first':'Peter', 'last':'Peterson'}
        ]
        "ip":[
            {'address': 'x.x.x.x', 'country': 'USA'},
            {'address': 'y.y.y.y', 'country': 'FRA'}
        ]
    }
    
    bulk.find({"appl_id": working_appl_id}).upsert() \
        .update(
            {
                '$addToSet': toBeAdded,
                '$setOnInsert': {
                    "appl_id": working_appl_id,
                 },
            }
        )
    
    res = bulk.execute()
    
    我的代码的输出不是期望的输出。我的代码的输出是这样的

    {
        'appl_id': 123,
        'name': [
            [
                {'first':'John', 'last':'Johnson'}, 
                {'first':'Peter', 'last':'Peterson'}
            ],
            [
                {'first':'Mayer', 'last':'Mayerson'}
                {'first':'John', 'last':'Johnson'}, 
            ],
          ],
          'ip': [
              [
                  {'address': 'x.x.x.x', 'country': 'USA'},
                  {'address': 'y.y.y.y', 'country': 'FRA'}
              ],
              [
                  {'address': 'x.x.x.x', 'country': 'USA'},
                  {'address': 'z.z.z.z', 'country': 'GER'}
              ]
          ]
    },
    {
        'appl_id': 456,
        'name': [
            {'first':'Will', 'last':'Willson'},
        ]
        'ip': [
            {'address': 'x.x.x.x', 'country': 'USA'}
        ]
    },
    
    我得到了一个带字典的数组,而不是一个带唯一字典的数组。(参见“名称”或“ip”键)


    如何在不创建数组的情况下删除执行upsert?
    TOBEADED
    变量由要插入的对象数组组成,当您尝试通过
    $addToSet
    $push
    更新方法插入数组时,它将插入整个数组本身,而不是该数组中的对象

    必须循环遍历数组中的对象,并通过单独的更新命令插入每个元素。或者您可以使用
    $each
    操作符让MongoDB为您完成这项工作

    下面是您的代码应该是什么:

    from pymongo import MongoClient
    
    
    client = MongoClient()
    
    db = client['temp']
    col = db['answer_temp']
    bulk = col.initialize_unordered_bulk_op()
    
    working_appl_id=123
    toBeAdded={
        "name":[
            {'first':'John', 'last':'Johnson'},
            {'first':'Peter', 'last':'Peterson'}
        ],
        "ip":[
            {'address': 'x.x.x.x', 'country': 'USA'},
            {'address': 'y.y.y.y', 'country': 'FRA'}
        ]
    }
    
    bulk.find({"appl_id": working_appl_id}).upsert() \
        .update(
        {
            '$addToSet': {
                "name": { "$each": toBeAdded["name"] },
                "ip": { "$each": toBeAdded["ip"] }
            },
            '$setOnInsert': {
                "appl_id": working_appl_id,
            },
        }
        )
    
    res = bulk.execute()
    
    
    注意:我还没有在本地测试过我的代码,所以如果出现问题一定要告诉我

    另外,
    initialize\u unordered\u bulk\u op
    也不推荐使用。您可以将其重新写入以下内容:

    from pymongo import MongoClient
    from pymongo.errors import BulkWriteError
    from pymongo import UpdateOne
    
    
    client = MongoClient()
    
    db = client['temp']
    col = db['answer_temp']
    # bulk = col.bulk_write()
    
    working_appl_id=123
    toBeAdded={
        "name":[
            {'first':'John', 'last':'Johnson'},
            {'first':'Peter', 'last':'Peterson'}
        ],
        "ip":[
            {'address': 'x.x.x.x', 'country': 'USA'},
            {'address': 'y.y.y.y', 'country': 'FRA'}
        ]
    }
    
    requests = []
    requests.append(
        UpdateOne(
            filter={
                "appl_id": working_appl_id
            },
            update={
                '$addToSet': {
                    "name": { "$each": toBeAdded["name"] },
                    "ip": { "$each": toBeAdded["ip"] }
                },
                '$setOnInsert': {
                    "appl_id": working_appl_id,
                },
            },
            upsert=True
        )
    )
    
    try:
        col.bulk_write(requests, ordered=False)
    except BulkWriteError as bwe:
        print(bwe.details)
    

    你的问题是什么?@D.SM对不起,我不习惯在这里发帖。谢谢你的反馈。我已经更新了帖子。我添加了代码的输出以及问题。这样更好吗?我想您需要的是中描述的,即使用$each.@D.SM谢谢您的帮助。文档确实很有用,尽管我尝试了广泛的搜索,但我以前找不到它。感谢您的回复。你所做的改变非常有效。我感谢你的帮助