Обновите все объекты в массиве и внутреннем массиве, которые соответствуют

У меня есть эта структура документа

{
    "_id": <OBJECT_ID>,
    "orders": [
         {
              "userId": 1,
              "handleName": "John Doe",
              "orderAmount": 3,
              "others": [
                   {
                        "userId": 1,
                        "handleName": "John Doe"
                   },
                   {
                        "userId": 2,
                        "handleName": "Maria Gigante"
                   }
              ]
         },
         {
              "userId": 2,
              "handleName": "Maria Gigante",
              "orderAmount": 2,
              "others": [
                   {
                        "userId": 1,
                        "handleName": "John Doe"
                   },
                   {
                        "userId": 2,
                        "handleName": "Maria Gigante"
                   }
              ]
         },
         {
              "userId": 1,
              "handleName": "John Doe",
              "orderAmount": 4,
              "others": [
                   {
                        "userId": 1,
                        "handleName": "John Doe"
                   },
                   {
                        "userId": 2,
                        "handleName": "Maria Gigante"
                   }
              ]
         },
         {
              "userId": 3,
              "handleName": "John Doe",
              "orderAmount": 4,
              "others": [
                   {
                        "userId": 1,
                        "handleName": "John Doe"
                   },
                   {
                        "userId": 2,
                        "handleName": "Maria Gigante"
                   }
              ]
         }
    ]
}

Я хотел бы обновить все объекты, которые имеют userId из 1 и handleName из John Doe. Обратите внимание, что объекты могут иметь одинаковые имена дескрипторов, но разные идентификаторы пользователей. Вот почему мне нужно сначала сопоставить его с userId.

Например, я хочу изменить имя дескриптора на Donald Stark.

Я хотел бы получить такой результат:

{
    "_id": <OBJECT_ID>,
    "orders": [
         {
              "userId": 1,
              "handleName": "Donald Stark",
              "orderAmount": 3,
              "others": [
                   {
                        "userId": 1,
                        "handleName": "Donald Stark"
                   },
                   {
                        "userId": 2,
                        "handleName": "Maria Gigante"
                   }
              ]
         },
         {
              "userId": 2,
              "handleName": "Maria Gigante",
              "orderAmount": 2,
              "others": [
                   {
                        "userId": 1,
                        "handleName": "Donald Stark"
                   },
                   {
                        "userId": 2,
                        "handleName": "Maria Gigante"
                   }
              ]
         },
         {
              "userId": 1,
              "handleName": "Donald Stark",
              "orderAmount": 4,
              "others": [
                   {
                        "userId": 1,
                        "handleName": "Donald Stark"
                   },
                   {
                        "userId": 2,
                        "handleName": "Maria Gigante"
                   }
              ]
         },
         {
              "userId": 3,
              "handleName": "John Doe",
              "orderAmount": 4,
              "others": [
                   {
                        "userId": 1,
                        "handleName": "Donald Stark"
                   },
                   {
                        "userId": 2,
                        "handleName": "Maria Gigante"
                   }
              ]
         }
    ]
}

Как это достигается?

Обновление: я забыл, что у меня есть еще один внутренний массив, который я тоже хочу обновить.


person Paul Ryan Lucero    schedule 13.05.2020    source источник
comment
Пожалуйста, обновите свой вопрос с кодом, который вы пробовали.   -  person quamrana    schedule 13.05.2020
comment
Отвечает ли это на ваш вопрос? фильтры массива в mongodb   -  person whoami - fakeFaceTrueSoul    schedule 13.05.2020
comment
@whoami извините, я забыл, что у меня также есть внутренний массив, который я хочу обновить. Я обновил свой вопрос, пожалуйста, взгляните на него еще раз.   -  person Paul Ryan Lucero    schedule 14.05.2020


Ответы (2)


мы можем использовать $[ идентификатор] оператор для обновления определенных объектов в массиве

поэтому ваш запрос на обновление должен выглядеть примерно так

db.collection.updateOne(
    { _id: <OBJECT_ID> }, // filter part, add the real objectId here
    { $set: { 'orders.$[order].handleName': 'Donald Stark' } }, // update part
    { arrayFilters: [{ 'order.userId': 1, 'order.handleName': 'John Doe' }] 
})

$[order] для обновления только тех объектов, которые соответствуют условиям в фильтрах массива


Обновлять

Если у вас есть внутренний массив, и вам нужно сделать то же самое для элементов внутри этого внутреннего массива, мы могли бы использовать что-то вроде этого

db.collection.updateOne(
    { _id: <OBJECT_ID> }, // filter part, add the real objectId here
    { $set: { 
        'orders.$[order].handleName': 'Donald Stark', // to set the handleName in the elements of the outer array
        'orders.$[].others.$[other].handleName': 'Donald Stark' // to set the handleName in the elements of the inner array
    } },
    { arrayFilters: [{ 'order.userId': 1, 'order.handleName': 'John Doe' }, { 'other.userId': 1, 'other.handleName': 'John Doe' }] }
)

мы использовали $[] для перебора всех элементов в массиве заказов, затем использовали $[other] для обновления определенных элементов во внутреннем массиве в соответствии с новым условием в фильтрах массива.

Надеюсь, поможет

person Mohammed Yousry    schedule 13.05.2020
comment
Действительно, это был бы правильный ответ, но я обновил свой вопрос. У меня также есть внутренний массив, содержащий аналогичные данные, которые я также хочу обновить. - person Paul Ryan Lucero; 14.05.2020
comment
хорошо, я обновил свой ответ, чтобы справиться с этим, не могли бы вы его проверить? - person Mohammed Yousry; 14.05.2020

Что-то подобное решит вашу проблему?

d = {
    "_id": <OBJECT_ID>,
    "orders": [
         {
              "userId": 1,
              "handleName": "John Doe",
              "orderAmount": 3
         },
         {
              "userId": 2,
              "handleName": "Maria Gigante",
              "orderAmount": 2
         },
         {
              "userId": 1,
              "handleName": "John Doe",
              "orderAmount": 4
         },
         {
              "userId": 3,
              "handleName": "John Doe",
              "orderAmount": 4
         }
    ]
}

def change_name(usr_id, old_name, new_name):
    for usr in d['orders']:
        if usr['userId'] == usr_id and usr['handleName'] == old_name:
            usr['handleName'] = new_name

change_name(1, 'John Doe', 'Donald Stark')
person Donatien    schedule 13.05.2020
comment
Извините, но эти данные находятся в коллекции документов db - person Paul Ryan Lucero; 13.05.2020