Учитывая этот документ сохранен в MongoDB
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2",
param3 : "val3"
}
}
Объект с новой информацией о param2
и param3
от внешнего мира , должен быть сохранен
var new_info = {
param2 : "val2_new",
param3 : "val3_new"
};
Я хочу объединить / наложить новые поля поверх существующего состояния объекта, чтобы param1 не был удален
Делая это
db.collection.update( { _id:...} , { $set: { some_key : new_info } }
Это приведет к тому, что MongoDB будет работать именно так, как было задано, и установит some_key в это значение. замена старого.
{
_id : ...,
some_key: {
param2 : "val2_new",
param3 : "val3_new"
}
}
Каким образом MongoDB может обновлять только новые поля (без явного указания их по одному)? чтобы получить это:
{
_id : ...,
some_key: {
param1 : "val1",
param2 : "val2_new",
param3 : "val3_new"
}
}
Я использую Java-клиент, но любой пример будет оценен
mongodb
mongodb-java
Эран Медан
источник
источник
Ответы:
Если я правильно понимаю вопрос, вы хотите обновить документ содержимым другого документа, но только полями, которых еще нет, и полностью игнорировать поля, которые уже установлены (даже если для другого значения).
Нет способа сделать это в одной команде.
Сначала вы должны запросить документ, выяснить, что вы хотите,
$set
а затем обновить его (используя старые значения в качестве подходящего фильтра, чтобы убедиться, что вы не получаете одновременных обновлений между ними).Еще одно прочтение вашего вопроса: вы довольны
$set
, но не хотите явно устанавливать все поля. Как бы вы передали данные тогда?Вы знаете, что можете сделать следующее:
источник
db.collection.update( { _id:...} , { $set: someObjectWithNewData, { $multi: true } } )
Я решил это с моей собственной функцией. Если вы хотите обновить указанное поле в документе, вам необходимо четко указать его.
Пример:
Если вы хотите обновить только param2, это неправильно:
Вы должны использовать:
Итак, я написал функцию примерно так:
источник
db.users.update( { _id: ObjectId("594dbc3186bb5c84442949b1") }, { $set: { resume: { url: "http://i.imgur.com/UFX0yXs.jpg" } } } )
Вы можете использовать точечную нотацию для доступа и установки полей глубоко внутри объектов, не влияя на другие свойства этих объектов.
Учитывая объект, который вы указали выше:
Мы можем обновить только
some_key.param2
иsome_key.param3
:Вы можете копаться так глубоко, как вам нравится. Это также полезно для добавления новых свойств к объекту, не затрагивая существующие.
источник
Лучшее решение - извлечь свойства из объекта и сделать их плоскими парами ключ-значение точка-нотация. Вы можете использовать, например, эту библиотеку:
https://www.npmjs.com/package/mongo-dot-notation
Оно имеет
.flatten
функцию, которая позволяет вам преобразовывать объект в плоский набор свойств, которые затем можно передать модификатору $ set, не беспокоясь о том, что любое свойство вашего существующего объекта БД будет удалено / перезаписано без необходимости.Взято из
mongo-dot-notation
документов:И тогда он образует идеальный селектор - он будет обновлять ТОЛЬКО данные свойства. РЕДАКТИРОВАТЬ: Мне нравится быть археологом несколько раз;)
источник
Mongo позволяет обновлять вложенные документы, используя
.
соглашение. Посмотрите: Обновление вложенных документов в mongodb . Вот еще один вопрос из прошлого об обновлении слиянием, например, тот, который вы ищете, я полагаю: MongoDB atomic update через документ 'merge'источник
Я имел успех, делая это так:
У меня есть функция, которая обрабатывает обновления моего профиля динамически
Примечание: «профиль» специфичен для моей реализации, это просто строка ключа, которую вы хотите изменить.
источник
Вы могли бы скорее сделать upsert, эта операция в MongoDB используется для сохранения документа в коллекцию. Если документ соответствует критериям запроса, он выполнит операцию обновления, в противном случае он вставит новый документ в коллекцию.
что-то похожее, как показано ниже
источник
Похоже, вы можете установить isPartialObject, который может выполнить то, что вы хотите.
источник
Если у вас есть несколько полей для обновления
источник
Запуск
Mongo 4.2
,db.collection.update()
может принимать агрегации трубопровода, что позволяет использовать операторы агрегации , такие , как$addFields
, который выводит все существующие поля из входных документов и вновь добавленных полей:Первая часть
{}
- это запрос на совпадение, который фильтрует, какие документы обновлять (в данном случае все документы).Вторая часть
[{ $addFields: { some_key: new_info } }]
- конвейер агрегации обновлений:$addFields
.$addFields
выполняет именно то, что вам нужно: обновление объекта так, чтобы новый объект перекрывался / сливался с существующим:{ param2: "val2_new", param3: "val3_new" }
будут объединены с существующимиsome_key
, оставивparam1
нетронутыми и либо добавив, либо заменив обаparam2
иparam3
.Не забывайте
{ multi: true }
, иначе будет обновлен только первый соответствующий документ.источник
в
Надеюсь, это поможет!
источник
использовать $ set сделать этот процесс
источник
Создайте объект обновления с именами свойств, включая необходимый точечный путь. («somekey.» + из примера OP), а затем используйте, чтобы выполнить обновление.
источник
Да, лучший способ - преобразовать нотацию объекта в строковое представление ключ-значение, как упомянуто в этом комментарии: https://stackoverflow.com/a/39357531/2529199
Я хотел бы выделить альтернативный метод с использованием этой библиотеки NPM: https://www.npmjs.com/package/dot-object который позволяет вам манипулировать различными объектами, используя точечную запись.
Я использовал этот шаблон для программного создания свойства вложенного объекта при принятии значения ключа в качестве переменной функции следующим образом:
Этот шаблон позволяет мне использовать как вложенные, так и одноуровневые свойства взаимозаменяемо и аккуратно вставлять их в Mongo.
Если вам нужно поиграть с объектами JS за пределами Mongo, особенно на стороне клиента, но иметь согласованность при работе с Mongo, эта библиотека предоставляет вам больше возможностей, чем упомянутый ранее
mongo-dot-notation
модуль NPM.PS Первоначально я хотел упомянуть это как комментарий, но, очевидно, мой представитель S / O недостаточно высок, чтобы оставить комментарий. Поэтому, не пытаясь вмешаться в комментарии SzybkiSasza, я просто хотел выделить альтернативный модуль.
источник
Я попытался
findAndModify()
обновить определенное поле в уже существующем объекте.https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/
источник
Вы должны подумать об обновлении объекта взаимозаменяемо, а затем просто сохранить объект с обновленными полями. Нечто подобное сделано ниже
источник
Вы должны использовать встроенные документы (строка объекта пути)
Итак, в JavaScript вы можете использовать Spread Operator (...) для обновления
источник