как я могу остановить "обновление" mongodb при обновлении поля вложенного массива? - PullRequest
3 голосов
/ 02 августа 2020

У меня есть такая база данных:

  {
        "universe":"comics",
        "saga":[
           {
              "name":"x-men",
              "characters":[
                 {
                    "character":"wolverine",
                    "picture":"618035022351.png"
                 },
                 {
                    "character":"wolverine",
                    "picture":"618035022352.png"
                 }
              ]
           }
        ]
     },
     {
        "universe":"dc",
        "saga":[
           {
              "name":"spiderman",
              "characters":[
                 {
                    "character":"venom",
                    "picture":"618035022353.png"
                 }
              ]
           }
        ]
     }

И с помощью этого кода я обновляю поле, где name: wolverine:

db.getCollection('collection').findOneAndUpdate(
  {
    "universe": "comics"
  },
  {
    $set: {
      "saga.$[outer].characters.$[inner].character": "lobezno",
      "saga.$[outer].characters.$[inner].picture": "618035022354.png"
    }
  },
  /*{
    "saga.characters": 1
  },*/
  {
    "arrayFilters": [
      {
        "outer.name": "x-men"
      },
      {
        "inner.character": "wolverine"
      }
    ],
      "multi":false
  }

)

Я хочу просто обновить первый объект где есть совпадение, и остановите его.

Например, если у меня есть массив из 100 000 элементов и объект, в котором есть совпадение, находится на десятой позиции, он обновит эту запись, но он будет продолжить просмотр всего массива, и это кажется мне неэффективным, хотя он уже выполнил обновление.

Примечание: если бы я выполнял обновление, используя _id внутри universe.saga.characters, вместо того, чтобы выполнять обновление с помощью name, все равно l oop через остальные элементы.

Как это сделать?

1 Ответ

1 голос
/ 02 августа 2020

Обновление с использованием arrayFilters условий

Я не думаю, что он найдет и обновит через l oop, и не имеет значения, имеет ли коллекция 100000 дополнительных документов, потому что здесь хорошее объяснение в $ [] и упомянул:

  • $[<identifier>] для определения идентификатора для обновления только тех элементов массива, которые соответствуют соответствующему документу фильтра в arrayFilters

  • В документе обновления используйте позиционный оператор $[<identifier>] с фильтром, чтобы определить идентификатор, на который вы затем ссылаетесь в документах фильтра массива . Но убедитесь, что у вас нет документа фильтра массива для идентификатора, если идентификатор не включен в документ обновления.

Обновление с использованием _id

Ваша точка,

Примечание: если бы я выполнял обновление, используя _id внутри universe.saga.characters вместо того, чтобы выполнять обновление с использованием имени, оно все равно было бы l oop через остальные элементы.

MongoDB обязательно будет использовать индекс _id. Вот хороший ответ на вопрос MongoDB Update Query Performance , из этого вы получите лучшее представление о пункте выше

Обновление с использованием индексированных полей

Вы можете создать индекс в соответствии с разделом запроса команды обновления. Здесь Индексы MongoDB и Стратегии индексирования объяснил, почему индекс важен,

В вашем примере позволяет см. примеры:

Пример 1: Если в документе есть 2 дополнительных документа, и при обновлении и проверке с помощью объяснение ("ExecutionStats") , предполагайте это обновление займет 1 секунду,

быстрое использование Пн go Игровая площадка (эта платформа не поддерживает запросы на обновление)

Пример 2: Если документ содержит 1000 вложенных документов и когда вы обновляете и проверяете с помощью объяснение ("ExecutionStats") , это может занять более 1 секунды,

Если указать индекс для полей (universe, saga.characters.character и saga.characters.picture) тогда определенно это займет меньше времени, чем обычно без индекса, главное преимущество индекса - он будет указывать на индексированные поля.

быстрое использование Пн go Игровая площадка (эта платформа будет не поддерживает запрос на обновление)

Создать индекс для ваших полей

db.maxData.createIndex({ 
    "universe": 1, 
    "saga.characters.character": 1, 
    "saga.characters.picture": 1
})

Для большего количества экспериментов используйте приведенные выше 2 примера данных с индексом и без индекса и проверки executionStats вы получите больше ясности.

...