Mongodb обновляет вставку, когда она должна обновляться

#mongodb #mongodb-query

#mongodb #mongodb-запрос

Вопрос:

Я использую запрос upsert для вставки / обновления документа в коллекции, однако запрос не всегда надежно обновляется. Иногда он вставляет другой документ, когда он должен обновляться. Вы можете увидеть запрос ниже — Обновленный запрос после того, как Алекс указал на это —

 db.test.update(
      { departmentID: "1",
        storeID: "1",
        customerID: "1"},
      {  
         $set: { 
           name: "Andy",
           rating: 1,
           score: 1
         },
         $setOnInsert: { 
             departmentID: "1",
             storeID: "1",
             customerID: "1"
         }
      },
      { upsert: true }
   );
  

Этот запрос в основном работает, но иногда в конечном итоге происходит то, что, когда приведенный выше запрос выполняется в быстрой последовательности (интервал 0,004 секунды), запрос заканчивает вставкой 2 документов с идентификаторами отдела-1, StoreID-1 и CustomerID-1, тогда как он должен был вставить только один документ и обновляться навторой экземпляр.

Комментарии:

1. Можно использовать уникальный индекс для DepartmentID, StoreID и CustomerID, но я не уверен в 2 вещах: 1) Погода, это приведет к снижению производительности запросов upsert. 2) Погода, которая будет работать или не будет работать в тех же условиях

2. И какой документ, по вашему мнению, должен был обновиться и какой документ был вставлен? Суть в том, что если вы хотите подать заявку, то она должна быть воспроизводимой. Мы бы хотели, чтобы вы показали этот воспроизводимый случай, поскольку для остальных из нас здесь «upserts» работают не так.

3. @NeilLunn созданные документы — {DepartmentID: «1», StoreID: «1», CustomerID: «1», имя: «Энди», рейтинг: 1, оценка: 1} {DepartmentID: «1», StoreID: «1», CustomerID: «1», имя: «Энди», рейтинг: 1, оценка: 1} Таким образом, первый документ должен был быть обновлен, а не вставлен новый документ.

4. Пожалуйста, покажите воспроизводимый случай. Я прошу вас доказать, что то, что, как вы утверждаете, происходит, действительно может произойти.

5. @NeilLunn как вы рекомендуете мне это сделать?

Ответ №1:

https://docs.mongodb.com/manual/reference/method/db.collection.update/#use-unique-indexes совершенно ясно об этом:

Чтобы избежать вставки одного и того же документа более одного раза, используйте upsert: true только в том случае, если поле запроса уникально проиндексировано.

Обновить

Есть несколько других проблем с запросом, благодаря указанию Нила Ланна. Синтаксис замены документа, используемый в результатах запроса, вставляется следующим документом:

 {
    "_id" : ObjectId(....),
    "name" : "Andy",
    "rating" : 1.0,
    "score" : 1.0
}
  

Этот документ не имеет идентификатора отдела, идентификатора хранилища или идентификатора клиента и не будет соответствовать фильтру при последовательных вызовах запроса на обновление. Т.Е. Выполнение одного и того же запроса 5 раз для пустой коллекции приведет к вставке 5 документов.

Правильный запрос должен использовать синтаксис обновления отдельных полей с комбинацией $set и $setOnInsert:

 db.test.update(
   { departmentID: "1",
     storeID: "1",
     customerID: "1"},
   {  
      $set: { 
        name: "Andy",
        rating: 1,
        score: 1
      },
      $setOnInsert: { 
          departmentID: "1",
          storeID: "1",
          customerID: "1"
      }
   },
   { upsert: true }
);
  

Комментарии:

1. Я прочитал вопрос как утверждающий, что «upserts» создают повторяющиеся записи, а не о «уникальных индексах». Я бы предположил, что проблема заключается в том, что «дублирующиеся» документы на самом деле не являются идентичными для предиката в операторе. Поэтому один и тот же предикат для уникального индекса ничего не изменит.

2. @NeilLunn если «приведенный выше запрос выполняется в быстрой последовательности», я думаю, документы идентичны, нет?

3. Um No. Операции по-прежнему являются атомарными, и тем более в современных версиях. Таким образом, на самом деле невозможно, чтобы в двух операциях был «не найден документ». Индекс приведет к ошибке, но на самом деле OP должен доказать обратное. Скорее всего, "1" иногда отправляется как 1 нечто большее, чем какое-либо случайное условие гонки.

4. @AlexBlex приведет ли добавление уникального индекса к снижению производительности обновления MongoDB?

5. @NeilLunn Я не уверен, что понимаю вторую часть вашего аргумента.