如果更新时某个属性的值为null,则不应将该属性添加到logging中

假设我有一个像这样的mongoose模式:

var mongoose = require('mongoose'); var Schema = mongoose.Schema; var testSchema = new Schema({ name: {type: String, required: true}, nickName: {type: String} }); var Test = module.exports = mongoose.model('Test', testSchema); 

我使用variablesTest来声明CRUD操作的方法。 从这个方法是更新,它定义如下:

 module.exports.updateTest = function(updatedValues, callback) { console.log(updatedValues); //this output is shown below Test.update( { "_id": updatedValues.id }, { "$set" : { "name" : updatedValues.name, "nickName" : updatedValues.nickName } }, { multi: false }, callback ); }; 

现在,我在我的节点路由器中使用这个方法如下:

 router.put('/:id', function(req, res, next) { var id = req.params.id, var name = req.body.name, var nickName = req.body.nickName req.checkBody("name", "Name is required").notEmpty(); var errors = req.validationErrors(); if(errors) { ........ } else { var testToUpdate = new Test({ _id: id, name: name, nickName: nickName || undefined }); Test.updateTest(testToUpdate, function(err, result) { if(err) { throw(err); } else { res.status(200).json({"success": "Test updated successfully"}); } }); } }); 

现在,如果我在数据库中保存新的logging,然后在数据库中看到它,那么它看起来像:

 { "_id" : ObjectId("ns8f9yyuo32hru0fu23oh"), //some automatically generated id "name" : "firstTest", "__v" : 0 } 

现在,如果我更新同一个文件而不更改任何内容,然后如果我看看数据库中的相同logging,那么我得到:

 { "_id" : ObjectId("ns8f9yyuo32hru0fu23oh"), //some automatically generated id "name" : "firstTest", "__v" : 0, "nickName" : null } 

你能看到昵称被设置为空吗? 我不希望它像这样工作。 我希望如果我的财产是空的,那么该财产不应该包括在logging中。

如果你还记得,我有控制台logging更新之前updatedValues。 (请参阅第二个代码块)。 所以,这里是logging的值:

 { "_id" : ObjectId("ns8f9yyuo32hru0fu23oh"), //some automatically generated id "name" : "firstTest" } 

我不知道为什么,但昵称是不存在的logging值,然后更新后,我得到nickName: null 。 我认为,问题出在第二个Code块。 你能检查一下吗?

注意:

其实我的模式中有更多的字段比我指定的更多。 有些字段也是对其他logging的引用。

我不会这样写,但我会告诉你为什么你的代码失败。

问题是你的$ set块

你正在select专门设置值的传递更新对象。如果该值是undefined你迫使mongo设置为null。

这是问题

例如,在DB中:

{ "_id" : ObjectId("ns8f9yyuo32hru0fu23oh"), "name" : "firstTest", "nickname": "jack", "__v" : 0 }

如果你通过testToUpdate = { name: 'foo' }你将以Test.update({ ... }, { $set: { name: 'foo', nickname: undefined }}

因为你得到了updatedValues.nickname的参数和那些没有定义

你想要什么是Test.update({ ... }, { $set: updatedValues } ,这就是Test.update({ ... }, { $set: { name: 'foo' } }

您不再为昵称提供密钥,因此不会将其设置为undefined / null。


我会使用mongoose插件,而不用担心手动将字段传递给模型

请参阅https://github.com/autolotto/mongoose-model-update

你可以定义可更新的字段,然后你可以这样做

model.update(req.body) ,不用担心这一切

即使你不想使用插件,你仍然可以做

Test.findByIdAndUpdate(id, { name, nickname }, callback)

问题在于你还在文档上添加了nickname属性 – 你只是把它设置为undefined ,但是与你认为不一样的东西不一样。

你想要的是不包括昵称属性,如果它是未定义的,你可以这样做:

 module.exports.updateTest = function(updatedValues, callback) { const set = { "name": updatedValues.name }; if (updatedValues.nickName) { set["nickName"] = updatedValues.nickName; } Test.update({ "_id": updatedValues.id }, { "$set": set}, { multi: false }, callback ); }; 

看看你的代码,你的更新方法有一个问题,不会帮助你获得你想要的结果。

这是你更新的代码:

 module.exports.updateTest = function(updatedValues, callback) { console.log(updatedValues); //this output is shown below Test.update( { "_id": updatedValues.id }, { "$set" : { "name" : updatedValues.name, "nickName" : updatedValues.nickName } }, { multi: false }, callback ); }; 

问题出在$set部分。

在MongoDB中,你不能通过给它undefined来取消在文档中的字段。 你应该使用$unset运算符。

所以你的更新代码应该是这样的:

 module.exports.updateTest = function(updatedValues, callback) { console.log(updatedValues); //this output is shown below const operators = {$set: {name: updatedValues.name}}; if (updatedValues.nickName) { operators.$set.nickName = updatedValues.nickName; } else { operators.$unset = {nickName: 1}; } Test.update( { "_id": updatedValues.id }, operators, { multi: false }, callback ); }; 

请注意, $unset的使用对于删除文档中已存在的字段是很重要的。

正如你在文档中所说的查询中使用$set

$ set操作符用指定的值replace字段的值。

所以你迫使在这里把未定义的值设置为null 。 您可以在模式的nickName字段中设置required : true ,或者尝试传递JS对象,而不是编写原始查询,而不是:

 Test.update( { "_id": updatedValues.id }, { "$set" : { "name" : updatedValues.name, "nickName" : updatedValues.nickName } }, { multi: false }, callback ); 

尝试做:

 var data = { name : updatedValues.name }; if(updatedValues.nickName){ data.nickName = updatedValues.nickName; } Model.update({ "_id": updatedValues.id }, data ,options, callback) 

请查看Mongoose文档中的这个链接,了解更多关于该方法的信息。