javascript - 如何使用 Sails.js 和 Waterline 更新 MongoDB 子文档中的特定键?

标签 javascript node.js mongodb sails.js waterline

尝试使用 Sails.js 和 Waterline ORM 更新 MongoDB 子文档中的单个键时遇到问题。这就是我的 person.js 模型的样子:

module.exports = {
    attributes: {
        name: { type: 'string', required: true },
        favorites: {
            type: 'json',
            defaultsTo: {
                color: null,
                place: null,
                season: null
            }
        }
    }
}

现在,假设我想从我的 Controller 更新特定人的名字和最喜欢的季节,我正在这样做:

Person.update({ id: '1' }, {
    name: 'Dan',
    favorites: {
        season: 'Summer'
    }
}).exec(function(error, updatedPerson) {

    console.log(updatedPerson);
});

当我运行这个时,favorites对象被完全替换为只有我更新的一个键(季节键),而不是在更新时保留其他两个键(颜色和位置)我想要的那个。我缺少什么?如何让它只更新我指定的 key ?

最佳答案

您可以使用.native() 模型上的方法可以直接访问 mongo 驱动程序,然后是 $set 运算符(operator)独立更新字段。但是,您需要首先将对象转换为具有点符号的单级文档,例如

{
    "name": "Dan",
    "favorites.season": "Summer"
}

这样您就可以将其用作:

var criteria = { "id": "1" },
    update = { "$set": { "name": "Dan", "favorites.season": "Summer" } },
    options = { "new": true };

// Grab an instance of the mongo-driver
Person.native(function(err, collection) {        
    if (err) return res.serverError(err);

    // Execute any query that works with the mongo js driver
    collection.findAndModify(
        criteria, 
        null,
        update,
        options,
        function (err, updatedPerson) {
            console.log(updatedPerson);
        }
    );
});

要转换需要更新的原始对象,请使用以下函数

var convertNestedObjectToDotNotation = function(obj){
    var res = {};
    (function recurse(obj, current) {
        for(var key in obj) {
            var value = obj[key];
            var newKey = (current ? current + "." + key : key);  // joined key with dot
            if  (value && typeof value === "object") {
                recurse(value, newKey);  // it's a nested object, so do it again
            } else {
                res[newKey] = value;  // it's not an object, so set the property
            }
        }
    })(obj);

    return res;
}

然后您可以在更新中调用它

var criteria = { "id": "1" },
    update = { "$set": convertNestedObjectToDotNotation(params) },
    options = { "new": true };

查看下面的演示。

var example = {
	"name" : "Dan",
	"favorites" : {
		"season" : "winter"
	}
};

var convertNestedObjectToDotNotation = function(obj){
	var res = {};
	(function recurse(obj, current) {
		for(var key in obj) {
			var value = obj[key];
			var newKey = (current ? current + "." + key : key);  // joined key with dot
			if	(value && typeof value === "object") {
				recurse(value, newKey);  // it's a nested object, so do it again
			} else {
				res[newKey] = value;  // it's not an object, so set the property
			}
		}
	})(obj);
	
	return res;
}


var update = { "$set": convertNestedObjectToDotNotation(example) };

pre.innerHTML = "update =  " + JSON.stringify(update, null, 4);
<pre id="pre"></pre>

关于javascript - 如何使用 Sails.js 和 Waterline 更新 MongoDB 子文档中的特定键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40741373/

相关文章:

javascript - 如何在 Javascript 中创建带命名空间的静态函数?

javascript - 如何使用 fabric.js Canvas 库在 Canvas 上创建的矩形内写入文本

javascript - 如何将一些 css 属性添加到已有的属性中?

node.js - 我想通过 npm 安装一些东西,但它说 'error' 和 'checkPermissions Missing'

javascript - Node.js http-proxy 丢弃 websocket 请求

mongodb - 为什么在 Spring 响应式 Mongo 中订阅有效而阻止无效?

node.js - 根据条件加入mongodb集合

node.js - 过滤数组时如何包含空数组

javascript - 未捕获的无效字符错误 : failed to convert to blob from base64 image

Node.js 登录/注册 Redis 问题