NodeJS + Mongoose: обновление всех полей в модели Mongoose - PullRequest
12 голосов
/ 21 февраля 2012

Я строю API, используя Node, MongoDB и Mongoose.Одна вещь, которая меня беспокоит, это то, что вы не можете установить несколько полей одновременно:

app.put('/record/:id', function(req, res) {
  Record.findById(req.params.id, function(err, doc) {
    if (!err) {
      doc.update(req.params);
      doc.save();
...

Однако, похоже, вам нужно обработать запрос на обновление и запустить его на объекте Model, ачем на объекте документа.Если вы не хотите назначать отдельные свойства и запускать save () в конце.

Есть ли способ выполнить это без написания запроса Mongo?

Ответы [ 8 ]

12 голосов
/ 22 января 2014

Ответ jsaak хорош, но не работает для вложенных объектов.Я подробно остановился на его ответе путем поиска и установки вложенных объектов.

Я добавил эти функции в файл utility.js

var _ = require('underscore');

exports.updateDocument = function(doc, SchemaTarget, data) {
    for (var field in SchemaTarget.schema.paths) {
       if ((field !== '_id') && (field !== '__v')) {
            var newValue = getObjValue(field, data);
            console.log('data[' + field + '] = ' + newValue);
            if (newValue !== undefined) {
                setObjValue(field, doc, newValue);
          }  
       }  
    }
    return doc;
};

function getObjValue(field, data) {
    return _.reduce(field.split("."), function(obj, f) { 
        if(obj) return obj[f];
    }, data);
}

function setObjValue(field, data, value) {
  var fieldArr = field.split('.');
  return _.reduce(fieldArr, function(o, f, i) {
     if(i == fieldArr.length-1) {
          o[f] = value;
     } else {
          if(!o[f]) o[f] = {};
     }
     return o[f];
  }, data);
}

, который реализован как:

var util = require('./utility');

app.put('/record/:id', function(req, res) {
  Record.findById(req.params.id, function(err, doc) {
    if (!err) {
      utils.updateDocument(doc, Record, req.params);
      doc.save();
    ...
10 голосов
/ 10 апреля 2014

Возможно, это изменилось с тех пор, как этот вопрос был задан впервые, но вы можете обновить несколько путей в Mongoose с помощью метода set ike:

// object
doc.set({
  path  : value,
  path2 : {
    path  : value
  }
});
doc.save();

Ссылки

8 голосов
/ 11 сентября 2013

прямое обновление не рекомендуется в соответствии с этим документом: http://mongoosejs.com/docs/2.7.x/docs/updating-documents.html

Я решил это так:

  Book.findOne({isbn: req.params.isbn}, function (err, book){
     if (err) {
        res.send(422,'update failed');
     } else {
        //update fields
        for (var field in Book.schema.paths) {
           if ((field !== '_id') && (field !== '__v')) {
              if (req.body[field] !== undefined) {
                 book[field] = req.body[field];
              }  
           }  
        }  
        book.save();
     }
  });
3 голосов
/ 06 ноября 2015

Если вы хотите обновить весь документ, вы можете удалить документ на основе его идентификатора и снова сохранить весь объект. Этот объект должен содержать данные для каждого поля документа монго.

Вот пример.

mongoDBCollectionObject.findOneAndRemove({ // -- it will delete the entire document
  _id: req.body.fieldsdata._id  // here fiedsdata is exact copy with modification  of previous data
  }, function(err, data) {
  var newFieldsData = new mongoDBCollectionObject(fieldsdata); //-- fieldsdata updated data
  newFieldsData.save(function(err, data) { // save document to that collection with updated data
    if (err) {
      console.log(err);
    } else
        res.json({
          success: true
          });
    });
  })
2 голосов
/ 21 февраля 2012

попробуйте обновить коллекцию без поиска, вот так

Record.update({_id:req.params.id}, {$set: { field: request.field }}, {upsert: true}, function(err{...})

Опция upsert создает документ, если не существует.

2 голосов
/ 21 февраля 2012

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

Есть ли способ сделать это без написания запроса Монго?

Очевидный ответ - обновить объект Model значением из Request. Что вы предлагаете ...

Если вы не хотите назначать отдельные свойства и запускать save () в конце.

Но, похоже, ты не хочешь этого делать? Похоже, вы хотите обновить объект Model непосредственно из объекта Request?

Вы можете сделать это, если вы действительно хотите. Вы просто просматриваете req.params и устанавливаете значения doc там, где это необходимо.

for(var i in req.params) {
  if(req.params[i] != doc[i]){
    doc[i] = req.params[i];
  }
}

Это должно быть так просто. Однако вы только хотите сделать это, если у вас есть целый набор проверочного кода для объектов Model. Весь смысл модели в том, что вы не хотите получать случайные данные в БД. В строке выше, как правило, «устанавливаются» правильные значения, но вам обязательно нужно будет включить код для аутентификации, авторизации и проверки вокруг этого простого цикла for.

1 голос
/ 23 августа 2016

Если у вас есть новый объект и вы хотите обновить весь объект в базе данных, вы можете обновить несколько полей одновременно, например:

  1. найти объект
  2. получить все пути схемы (поля)
  3. сохранить новый объект.

SomeModel.findOne({ 'id': 'yourid' },function (err, oldObject) {
	if (err) return handleError(err);

	// get all schema paths (fields)
	SomeModel.schema.eachPath(function(path) {

	    // leave __id and __v alone
	    if (path != '_id' && path != '__v') {
	    	// update the data from new object
	    	oldObject[path] = newObject[path];
	    }
	})

	oldObject.save(function(err) {
		if (err)
		console.log(err)
	});
})
0 голосов
/ 22 июня 2019

Аккуратный и чистый подход будет использовать async await и findOneAndRemove вместе с create Вот пример кода

try {
            let resp = await this.findOneAndRemove({ _id: req.body._id });
            let entry = await this.create(req.body);

    } catch (err) {

    }

Не забудьте отметитьвся функция как async

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...