Mongodb upsert только обновляет выбранные поля, но вставляет все

Я пытаюсь использовать upsert в MongoDB для обновления одного поля в документе, если он найден или вставляет целый новый документ с большим количеством полей. Проблема заключается в том, что мне кажется, что MongoDB либо заменяет каждое поле, либо вставляет подмножество полей в свою upsert-операцию, то есть не может вставлять больше полей, чем на самом деле хочет обновить.

Я хочу сделать следующее:

  • Я запрашиваю одно уникальное значение
  • Если документ уже существует, только новое значение времени (позволяет вызывать его «lastseen») обновляется до нового значения
  • Если документ не существует, я добавлю его с длинным списком разных пар ключ/значение, которые должны оставаться статическими в течение оставшейся части его срока службы.

Давайте проиллюстрируем:

В этом примере из моего понимания будет обновлено значение «lastseen», если «имя» найдено, но если «имя» не найдено, оно будет вставлять только «имя» + «последний».

db.somecollection.update({name: "some name"},{ $set: {"lastseen": "2012-12-28"}}, {upsert:true})

Если я добавил еще два поля (пары ключ/значение) ко второму аргументу и сбросил значение $ set, тогда каждое поле будет заменено при обновлении, но будет иметь желаемый эффект для вставки. Есть ли что-то вроде $ insert или подобное для выполнения операций только при вставке?

Поэтому мне кажется, что я могу получить только одно из следующего:

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

Правильно ли я понимаю? Если да, можно ли это решить с помощью одной операции?

10
nl ja de
Есть ли причина, почему эти пары ключевого значения не могут использоваться в предложении find upsert?
добавлено автор Sammaye, источник
Причина в том, что есть только одно поле, в котором я знаю значение в этой точке. Я не хочу, чтобы запрос возвращал 0 ударов, если точное совпадение полей не совпадает. Единственное поле, которое я знаю, значение будет определять, будет ли его новая вставка или обновление.
добавлено автор agnsaft, источник

2 ответы

MongoDB 2.4 has $setOnInsert

db.somecollection.update(
    {name: "some name"},
    {
        $set: {
            "lastseen": "2012-12-28"
        },
        $setOnInsert: {
            "firstseen":   # set on insert, not on update
        }
    },
    {upsert:true}
)
29
добавлено

Для этого есть запрос функции ( https://jira.mongodb.org/browse/SERVER-340 ) который разрешен в 2.3. Нечетные выпуски на самом деле выпущены, так что это будет в стабильной версии 2.4.

Таким образом, в нынешних стабильных версиях нет реального способа сделать это. Я боюсь, что единственный метод состоит в том, чтобы фактически выполнить 3 условных запроса atm: 1, чтобы проверить строку, а затем if , чтобы либо вставить, либо обновить.

Я полагаю, что если бы у вас были настоящие проблемы с блокировкой здесь, вы могли бы выполнять эту функцию с единственным JS, но это зло, но это заблокировало бы это обновление до одного потока.

8
добавлено
Спасибо друг. Я действительно искал в Джире, чтобы искать такую ​​информацию, но, видимо, я пропустил ее.
добавлено автор agnsaft, источник
DBA - русскоговорящее сообщество
DBA - русскоговорящее сообщество
1 345 участник(ов)

Общаемся и обсуждаем темы, посвященные DBA, PostgreSQL, Redis, MongoDB, MySQL, neo4j, riak и т.д. См. также: @devops_ru, @kubernetes_ru, @docker_ru, @nodejs_ru Рекомендуем сразу отключить уведомления, чтобы пребывание здесь было полезным и комфортным.

MongoDB Russian
MongoDB Russian
1 086 участник(ов)

> db.stats() https://combot.org/chat/-1001035023078