Javascript 如何使用Sails.js&;更新MongoDB子文档中的特定密钥;水线?
我在尝试使用Sails.js和Waterline ORM更新MongoDB子文档中的单个键时遇到了一个问题。这就是我的Javascript 如何使用Sails.js&;更新MongoDB子文档中的特定密钥;水线?,javascript,node.js,mongodb,sails.js,waterline,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: {
person.js
模型的外观:
module.exports = {
attributes: {
name: { type: 'string', required: true },
favorites: {
type: 'json',
defaultsTo: {
color: null,
place: null,
season: null
}
}
}
}
现在,假设我想从我的控制器中更新特定人员的姓名和最喜爱的季节,我正在这样做:
Person.update({ id: '1' }, {
name: 'Dan',
favorites: {
season: 'Summer'
}
}).exec(function(error, updatedPerson) {
console.log(updatedPerson);
});
当我运行此操作时,
favorites
对象将被完全替换,只保留我更新的一个键(季节键),而不是保留另外两个键(颜色和位置),同时只更新我想要的一个键。我错过了什么?如何让它只更新我指定的键?只需使用以下命令更改查询:
Person.update({ id: '1' },{ name: 'Dan',favorites: { $set: {season: Summer'}}}})
您可以在模型上使用直接访问mongo驱动程序的方法,然后使用操作符独立更新字段。但是,您需要首先将对象转换为具有点符号的一级文档,如
{
"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示例={
“姓名”:“丹”,
“收藏夹”:{
“季节”:“冬天”
}
};
var convertedObjectToDotNotation=函数(obj){
var res={};
(函数递归(obj,当前){
for(obj中的var键){
var值=obj[键];
var newKey=(当前?当前+“+键:键);//用点连接键
if(值和类型值==“对象”){
recurse(value,newKey);//这是一个嵌套对象,所以请再次执行
}否则{
res[newKey]=value;//它不是对象,所以设置属性
}
}
})(obj);
返回res;
}
var update={“$set”:convertedObjectToDotNotation(示例)};
pre.innerHTML=“update=“+JSON.stringify(update,null,4)代码>
问题是,需要更新的参数是由使用我们的API的客户端应用程序发送的。我们不能强迫API的用户使用$set等来发送它。他们会向我们发送一个原始JSON对象。还可以吗?检查所有要更新的嵌套对象,然后在该对象上使用$set。效果很好!尽管我应该补充一点,我必须引用它,因为本机查询{“id”:1}
不能自动工作,因为MongoDB使用ObjectId作为id。