Подтвердить что ты не робот

Как удалить элемент из дважды вложенного массива в документе MongoDB.

У меня есть структура документа что-то вроде следующих:

{
"_id" : "777",
"someKey" : "someValue",
"someArray" : [
    {
        "name" : "name1",
        "someNestedArray" : [
            {
                "name" : "value"
            },
            {
                "name" : "delete me"
            }
        ]
    }
  ]
}

Я хочу удалить вложенный элемент массива со значением "delete me".

Я знаю, что могу найти документы, которые соответствуют этому описанию, с использованием вложенных выражений $elemMatch. Каков синтаксис запроса для удаления рассматриваемого элемента?

4b9b3361

Ответ 1

Чтобы удалить данный предмет, вы действительно собираетесь использовать обновление. Более конкретно, вы собираетесь выполнить обновление с помощью команды $pull, которая удалит элемент из массива.

db.temp.update(
  { _id : "777" },
  {$pull : {"someArray.0.someNestedArray" : {"name":"delete me"}}}
)

Здесь немного "волшебства". Использование .0 означает, что мы знаем, что мы модифицируем 0-й элемент someArray. Использование {"name":"delete me"} означает, что мы знаем точные данные, которые мы планируем удалить.

Этот процесс работает очень хорошо, если вы загружаете данные в клиент и затем выполняете обновление. Этот процесс работает менее эффективно, если вы хотите выполнять "общие" запросы, которые выполняют эти операции.

Мне кажется, что проще всего понять, что для обновления массивов поддокументов обычно требуется, чтобы в какой-то момент у вас есть оригинал в памяти.


В ответ на первый комментарий ниже вы, вероятно, можете помочь в своей ситуации, немного изменив структуру данных

"someObjects" : {
  "name1":  {
        "someNestedArray" : [
            {
                "name" : "value"
            },
            {
                "name" : "delete me"
            }
        ]
    }
}

Теперь вы можете сделать {$pull : { "someObjects.name1.someNestedArray" : ...

Вот проблема с вашей структурой. MongoDB не имеет очень хорошей поддержки для манипулирования "подмассивами". В вашей структуре есть массив объектов, и эти объекты содержат массивы из большего количества объектов.

Если у вас есть следующая структура, у вас будет трудное время, используя такие вещи, как $pull:

array [
  { subarray : array [] },
  { subarray : array [] },
]

Если ваша структура выглядит так и вы хотите обновить subarray, у вас есть два варианта:

  • Измените структуру, чтобы вы могли использовать $pull.
  • Не используйте $pull. Загрузите весь объект в клиент и используйте findAndModify.

Ответ 2

Как прокомментировал @Melkor (вероятно, сам должен быть ответом),

Если вы не знаете индекс, используйте:

    {_id: TheMainID, "theArray._id": TheArrayID}, {$pull: 
    {"theArray.$.theNestedArray": {_id: theNestedArrayID}}}

Ответ 3

Другой пример и использование может быть таким:

{

    "company": {
        "location": {
            "postalCode": "12345",
            "Address": "Address1",
            "city": "Frankfurt",
            "state": "Hessen",
            "country": "Germany"
        },
        "establishmentDate": "2019-04-29T14:12:37.206Z",
        "companyId": "1",
        "ceo": "XYZ"
    },
    "items": [{
            "name": "itemA",
            "unit": "kg",
            "price": "10"
        },
        {
            "name": "itemB",
            "unit": "ltr",
            "price": "20"
        }

    ]
}
  1. DELETE: Mongodb Запрос на удаление элемента B:
db.getCollection('test').update(   
    {"company.companyId":"1","company.location.city":"Frankfurt"},
    {$pull : {"items" : {"name":"itemB"}}}
)
  1. НАЙТИ: Найти запрос для элемента В:
db.getCollection('test').find(
    {"company.companyId":"1","company.location.city":"Frankfurt","items.name":"itemB"},
    { "items.$": 1 }
)

3. UPDATE: обновить запрос для элемента B:

db.getCollection('test').update
(
 {"company.companyId":"1","company.location.city":"Frankfurt","items.name":"itemB"},
 { $set: { "items.$[].price" : 90 }}, 
   { multi: true });

Ответ 4

В MongoDB 3.6 добавлен оператор $ [], который упрощает обновление массивов, содержащих встроенные документы. Таким образом, проблема может быть решена с помощью:

db.test.update(
  { _id : "777" },
  {$pull : {"someArray.$[].someNestedArray" : {"name":"delete me"}}}
)