Как удалить элемент из дважды вложенного массива в документе MongoDB - PullRequest
39 голосов
/ 08 марта 2011

У меня есть структура документа, которая выглядит примерно так:

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

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

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

Ответы [ 3 ]

42 голосов
/ 08 марта 2011

Чтобы удалить рассматриваемый элемент, вы фактически собираетесь использовать обновление.Точнее, вы собираетесь выполнить обновление с помощью команды $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, у вас есть два варианта:

  1. Измените структуру, чтобы вы могли использовать $pull.
  2. Не использовать $pull.Загрузите весь объект в клиент и используйте findAndModify.
5 голосов
/ 02 января 2017

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

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

    {_id: TheMainID, theArray._id: TheArrayID}, {$pull: 
    {"theArray.$.theNestedArray": {_id: theNestedArrayID}}}
0 голосов
/ 29 апреля 2019

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

{

    "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. УДАЛИТЬ: Запрос Mongodb для удаления ItemB:
db.getCollection('test').update(   
    {"company.companyId":"1","company.location.city":"Frankfurt"},
    {$pull : {"items" : {"name":"itemB"}}}
)
НАЙТИ: Найти запрос для элемента B:
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 });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...