Обновление схемы mongodb с помощью findByIdAndUpdate с помощью node.js [duplicate]

Честно, в этом случае вам не нужно 0xFF. Если вы сделали cv2.waitkey(0) == ord(q), это все равно будет работать. 0xFF используется только для маскировки последней 8bits последовательности, а ord () любого символа клавиатуры не будет больше 255. Вы можете ссылаться на эту таблицу ASCII , чтобы найти числовую значения любого символа клавиатуры.

119
задан Eran Medan 24 April 2012 в 02:33
поделиться

12 ответов

Если я правильно понял вопрос, вы хотите обновить документ с содержимым другого документа, но только те поля, которые еще не присутствуют, и полностью игнорировать уже установленные поля (даже если это другое значение).

Невозможно сделать это в одной команде.

Сначала вы должны запросить документ, выяснить, что вы хотите $set, а затем обновить его (используя старые значения в качестве фильтра соответствия, чтобы убедиться, что вы не получаете параллельных обновлений между ними.


Другое чтение вашего вопроса состояло бы в том, что вы довольны $set, но не хотите для явного задания всех полей. Как вы могли бы передать данные?

Вы знаете, что можете сделать следующее:

db.collection.update(  { _id:...} , { $set: someObjectWithNewData } 
78
ответ дан Thilo 20 August 2018 в 13:08
поделиться
  • 1
    Что делать, если вы хотите явно установить все поля ... – morgs32 25 November 2014 в 04:07
  • 2
    Если вы хотите безоговорочно установить все поля, вы можете использовать параметр $ multi , например: db.collection.update( { _id:...} , { $set: someObjectWithNewData, { $multi: true } } ) – z.ky 11 May 2016 в 13:17
  • 3
    Нет параметра $ multi. Существует несколько параметров (с которыми вы связаны), но это не влияет на обновление полей. Он контролирует, обновляете ли вы один документ или все документы, соответствующие параметру запроса. – Bob Kerns 25 May 2016 в 00:09
  • 4
    Это не имеет никакого смысла. При работе с монго предпочтительнее также для обновлений иметь атомные операции. Первое чтение вызывает грязное чтение, когда кто-то другой меняет ваши данные. И поскольку у mongo нет транзакций, это с радостью испортит вам данные. – froginvasion 26 January 2017 в 11:38
  • 5
    @froginvasion: вы можете сделать его атомарным, используя старые значения в качестве фильтра соответствия для обновления. Таким образом, ваше обновление не будет выполнено, если в то же время возникло противоречивое одновременное обновление. Затем вы можете обнаружить это и действовать соответствующим образом. Это называется оптимистической блокировкой. Но да, это зависит от того, как ваше приложение правильно его реализует, у самого Монго нет встроенных транзакций. – Thilo 27 January 2017 в 00:40

Сделайте объект обновления с именами свойств, включая нужный путь. («somekey.» + из примера OP), а затем используйте это обновление.

//the modification that's requested
updateReq = { 
   param2 : "val2_new",
   param3 : "val3_new"   
}

//build a renamed version of the update request
var update = {};
for(var field in updateReq){
    update["somekey."+field] = updateReq[field];
}

//apply the update without modifying fields not originally in the update
db.collection.update({._id:...},{$set:update},{upsert:true},function(err,result){...});
0
ответ дан Andrew 20 August 2018 в 13:08
поделиться

Да, лучший способ - преобразовать нотацию объекта в плоское представление строки значения ключа, как указано в этом комментарии: https://stackoverflow.com/a/39357531/2529199

Я хотел выделить альтернативный метод, используя эту библиотеку NPM: https://www.npmjs.com/package/dot-object , который позволяет вам манипулировать различными объектами с использованием точечной нотации.

Я использовал этот шаблон для программного создания свойства вложенного объекта при принятии значения ключа в качестве функциональной переменной следующим образом:

const dot = require('dot-object');

function(docid, varname, varvalue){
  let doc = dot.dot({
      [varname]: varvalue 
  });

  Mongo.update({_id:docid},{$set:doc});
}

Этот шаблон позволяет мне использовать вложенные как одноуровневые свойства взаимозаменяемо и вставлять их в Mongo.

Если вам нужно поиграть с объектами JS за пределами Mongo, особенно на стороне клиента, но иметь согласованность при работе с Mongo, эта библиотека дает вам больше возможностей, чем ранее упомянутый модуль mongo-dot-notation NPM.

PS Мне изначально хотелось просто упомянуть об этом в качестве комментария, но, судя по всему, моя реплика S / O недостаточно высока, чтобы p ost комментарий. Так что, не пытаясь вникать в комментарий SzybkiSasza, просто хотелось выделить альтернативный модуль.

1
ответ дан Ashwin Shankar 20 August 2018 в 13:08
поделиться

Mongo позволяет вам обновлять вложенные документы, используя соглашение .. Посмотрите: Обновление вложенных документов в mongodb . Вот еще один вопрос из прошлого о обновлении слияния, например тот, который вы ищете. Я полагаю: атомное обновление MongoDB через документ 'merge'

7
ответ дан Community 20 August 2018 в 13:08
поделиться

использовать $ set, этот процесс

.update({"_id": args.dashboardId, "viewData._id": widgetId}, {$set: {"viewData.$.widgetData": widgetDoc.widgetData}})
.exec()
.then(dashboardDoc => {
    return {
        result: dashboardDoc
    };
}); 
0
ответ дан KARTHIKEYAN.A 20 August 2018 в 13:08
поделиться

У меня был успех, делающий это следующим образом:

db.collection.update(  { _id:...} , { $set: { 'key.another_key' : new_info  } } );

У меня есть функция, которая динамически обрабатывает мои обновления профиля

function update(prop, newVal) {
  const str = `profile.${prop}`;
  db.collection.update( { _id:...}, { $set: { [str]: newVal } } );
}

Примечание: «Профиль» относится к моему реализация, это просто строка ключа, которую вы хотели бы изменить.

1
ответ дан Matt Smith 20 August 2018 в 13:08
поделиться

Похоже, вы можете установить isPartialObject , который может выполнить то, что вы хотите.

1
ответ дан Patrick Tescher 20 August 2018 в 13:08
поделиться
  • 1
    попробовал. он не позволяет вам сохранять частичные объекты, если я не ошибаюсь ... но спасибо – Eran Medan 24 April 2012 в 02:46

Вы можете использовать dot-notation для доступа и установки полей глубоко внутри объектов, не влияя на другие свойства этих объектов.

Учитывая объект, указанный вами выше:

> db.test.insert({"id": "test_object", "some_key": {"param1": "val1", "param2": "val2", "param3": "val3"}})
WriteResult({ "nInserted" : 1 })

Мы можем обновить только some_key.param2 и some_key.param3:

> db.test.findAndModify({
... query: {"id": "test_object"},
... update: {"$set": {"some_key.param2": "val2_new", "some_key.param3": "val3_new"}},
... new: true
... })
{
    "_id" : ObjectId("56476e04e5f19d86ece5b81d"),
    "id" : "test_object",
    "some_key" : {
        "param1" : "val1",
        "param2" : "val2_new",
        "param3" : "val3_new"
    }
}

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

9
ответ дан Samir Talwar 20 August 2018 в 13:08
поделиться

Лучшее решение состоит в том, чтобы извлечь свойства из объекта и сделать их парами ключ-значение с точечной точкой. Вы можете использовать, например, эту библиотеку:

https://www.npmjs.com/package/mongo-dot-notation

Он имеет .flatten, которая позволяет изменять объект в плоский набор свойств, который затем может быть задан модификатору $ set, не опасаясь, что любое свойство вашего существующего объекта БД будет удалено / перезаписано без необходимости.

mongo-dot-notation docs:

var person = {
  firstName: 'John',
  lastName: 'Doe',
  address: {
    city: 'NY',
    street: 'Eighth Avenu',
    number: 123
  }
};



var instructions = dot.flatten(person)
console.log(instructions);
/* 
{
  $set: {
    'firstName': 'John',
    'lastName': 'Doe',
    'address.city': 'NY',
    'address.street': 'Eighth Avenu',
    'address.number': 123
  }
}
*/

И затем он формирует идеальный селектор - он обновит ТОЛЬКО заданные свойства. EDIT: Мне нравится быть археологом несколько раз;)

8
ответ дан SzybkiSasza 20 August 2018 в 13:08
поделиться

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

Пример:

{
    _id : ...,
    some_key: { 
        param1 : "val1",
        param2 : "val2",
        param3 : "val3"
    }
}

Если вы хотите обновить только param2, это неправильно:

db.collection.update(  { _id:...} , { $set: { some_key : new_info  } }  //WRONG

Вы должны использовать:

db.collection.update(  { _id:...} , { $set: { some_key.param2 : new_info  } } 

Итак, я написал какую-то функцию:

function _update($id, $data, $options=array()){

    $temp = array();
    foreach($data as $key => $value)
    {
        $temp["some_key.".$key] = $value;
    } 

    $collection->update(
        array('_id' => $id),
        array('$set' => $temp)
    );

}

_update('1', array('param2' => 'some data'));
75
ответ дан TheMerovingian 20 August 2018 в 13:08
поделиться
  • 1
    Это должен быть принятый ответ. Для лучшей функции flattenObject см. gist.github.com/penguinboy/762197 – steph643 7 April 2015 в 09:19
  • 2
    Спасибо, что ваш ответ помог мне. Я смог изменить значение конкретного ключа пользователя в коллекции пользователей следующим образом: db.users.update( { _id: ObjectId("594dbc3186bb5c84442949b1") }, { $set: { resume: { url: "http://i.imgur.com/UFX0yXs.jpg" } } } ) – Luke Schoen 25 June 2017 в 01:51

В Mongo 3.6 существует функция mergeObjects, которая делает именно то, что вам нужно:

https://docs.mongodb.com/manual/reference/operator/aggregation/mergeObjects/

-1
ответ дан Tim Babych 20 August 2018 в 13:08
поделиться
  • 1
    Это «оператор агрегации». и не имеет ничего общего с "обновлением" документ, хранящийся в коллекции, что и задается вопросом. – Neil Lunn 29 April 2018 в 01:29
    // where clause DBObject
    DBObject query = new BasicDBObject("_id", new ObjectId(id));

    // modifications to be applied
    DBObject update = new BasicDBObject();

    // set new values
    update.put("$set", new BasicDBObject("param2","value2"));

   // update the document
    collection.update(query, update, true, false); //3rd param->upsertFlag, 4th param->updateMultiFlag

Если у вас есть несколько полей для обновления

        Document doc = new Document();
        doc.put("param2","value2");
        doc.put("param3","value3");
        update.put("$set", doc);
0
ответ дан Vino 20 August 2018 в 13:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: