MongoDB: обновить элемент вложенного массива или вставить его, если он не существует

#javascript #mongodb #meteor #minimongo

#javascript #mongodb #метеор #minimongo

Вопрос:

Вот какой может быть структура документа в моем случае:

 {
    "_id" : "P9H59RuSbnm45erj7",
    "description" : [
        {
            "content" : "Something",
            "language" : "en",
            "timestamp" : 1476958705
        },
        {
            "content" : "Irgendetwas",
            "language" : "de",
            "timestamp" : 1476958705
        }
    ]
}
  

Теперь я хочу обновить содержимое определенного языка. Но в массиве описания могут отсутствовать языки.

 {
    "_id" : "P9H59RuSbnm45erj7",
    "description" : [
        {
            "content" : "Something",
            "language" : "en",
            "timestamp" : 1476958705
        }
    ]
}
  

Итак, что я делаю, это сначала проверить, существует ли язык, затем

  1. Если он существует, я сделаю простое обновление / $set
  2. Если он не существует, я сделаю обновление / $addToSet

Мой вопрос в том, можно ли это упростить. Действительно ли мне нужно проверять существующий язык, а затем использовать два разных запроса на обновление? При этом код загружается…

Я использую этот код в своем приложении meteor, поэтому я использую minimongo.

 if (Collection.find({ _id: 'P9H59RuSbnm45erj7', 'description.language': 'en' }).count() > 0) {
    Collection.update(
        {
            _id                   : 'P9H59RuSbnm45erj7',
            'description.language': 'en'
        },
        {
            $set: {
                'description.$.content'  : value,
                'description.$.timestamp': Math.floor(Date.now() / 1000)
            }
        }
    );
}
else {
    Collection.update(
        { _id: 'P9H59RuSbnm45erj7' },
        {
            $addToSet: {
                description: {
                    content  : value,
                    language : 'en',
                    timestamp: Math.floor(Date.now() / 1000)
                }
            }
        }
    );
}
  

Ответ №1:

 db.Test8.update(
      { _id: 1, "description.language":{$eq:"en"} },
      {
                $set: { "description.$.content": "content5" }
      },
      {}, function (err, result) {

          // if result.nMatched == 0 then make your $addToSet
          // because there are no query

       }
    );
  

Преимущество наличия запроса в этом was заключается в том, что большую часть времени выполняется 1 запрос вместо 2. И только в редких случаях 2-запроса.

В зависимости от вашего наиболее часто используемого сценария. Как вы говорите, большую часть времени происходит обновление, тогда вы можете выполнить 1 запрос вместо 2 запросов.

Я не знаю другого способа улучшить его.

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

1. Я думаю, что в моем случае большую часть времени это обновление и редко нажатие

2. @user3142695 Я инвертирую запрос 2 с запросом 1.