Node.js Mongoose:将元素推入或替换到数组中

Node.js Mongoose:将元素推入或替换到数组中,node.js,mongodb,mongoose,mongodb-query,Node.js,Mongodb,Mongoose,Mongodb Query,我正在使用(node.js中的MongoDB),在阅读了这个答案之后: 我还有一个问题: 在同一句话中是否可以这样做:将元素推入数组中,或者如果数组中存在此元素,则替换它 也许是这样的?(这个例子不起作用) 消息错误: errmsg:“异常:无法同时更新“读卡器”和“读卡器” 参考: 谢谢大家! 在一个请求中不允许在同一属性路径上执行多个操作,主要原因是这些操作本身在文档更新时引擎分配它们的方式中“没有特定顺序”,因此存在应报告为错误的冲突 因此,这方面的基本抽象是,您要执行“两

我正在使用(node.js中的MongoDB),在阅读了这个答案之后:

我还有一个问题:

  • 在同一句话中是否可以这样做:将元素推入数组中,或者如果数组中存在此元素,则替换它
也许是这样的?(这个例子不起作用)

消息错误:

errmsg:“异常:无法同时更新“读卡器”和“读卡器”

参考:


谢谢大家!

在一个请求中不允许在同一属性路径上执行多个操作,主要原因是这些操作本身在文档更新时引擎分配它们的方式中“没有特定顺序”,因此存在应报告为错误的冲突

因此,这方面的基本抽象是,您要执行“两个”更新操作,一个是“替换”存在的元素,另一个是“推送”不存在的新元素

实现这一点的最佳方法是使用,虽然“技术上”仍然是“两个”更新操作,但无论满足何种条件,它都只是一个“单个”请求和响应:

var bulk=Model.collection.initializeOrderedBulkOp();
bulk.find({“\u id”:id,“readers.user”:req.user.id}).updateOne({
“$set”:{“readers.$.someData”:data}
});
bulk.find({“\u id”:id,“readers.user”:{“$ne”:req.user.id}}).updateOne({
“$push”:{“readers”:{“user”:req.user.id,“someData”:data}
});
bulk.execute(函数(错误、结果){
//在这里处理结果
});
如果您确实“需要”结果中的更新对象,那么这将真正成为一个“可能”的多请求,遵循未找到数组元素的逻辑:

Model.findOneAndUpdate(
{“_id”:id,“readers.user”:req.user.id},
{“$set”:{“readers.$.someData”:data},
{“新”:正确},
功能(错误、文档){
if(err)//处理错误;
如果(!doc){
Model.findOneAndUpdate(
{“_id”:id,“readers.user”:{“$ne”:req.user.id},
{“$push”:{“readers”:{“user”:req.user.id,“someData”:data}},
{“新”:正确},
功能(错误、文档){
//或者在第一个不匹配时返回这里
}
);
}否则{
//第一次尝试时已更新,请回复
}
}
);
再次使用您喜欢的方法,即不将回调嵌套在类似或嵌套的承诺结果中,以避免一个操作固有的基本缩进蠕变依赖于另一个操作的结果

基本上,如果您真的需要,可以“批量”执行更新,然后“获取”数据,这样可能会更高效


完整列表
var async=require('async'),
mongoose=require('mongoose')
Schema=mongoose.Schema;
猫鼬mongodb://localhost/test');
var userSchema=新模式({
名称:String
});
var dataSchema=新模式({
用户:{type:Schema.Types.ObjectId,ref:'user'},
someData:String
},{u id:false});
var testSchema=新模式({
名称:String,
读者:[数据模式]
});
var User=mongoose.model('User',userSchema),
Test=mongoose.model('Test',testSchema);
var userId=null,
id=null;
异步系列(
[
//干净的模型
函数(回调){
async.each([User,Test],函数(model,callback){
删除({},回调);
},回调);
},
//创建用户
函数(回调){
create({name:'bill'},函数(err,User){
userId=user.\u id;
回调(err);
});
},
函数(回调){
Test.create({name:'Topic'},函数(err,Topic){
id=主题。\u id;
日志(“初始状态:”);
console.log(主题);
回调(err);
});
},
//第一次插入阵列第二次更新匹配1已修改
函数(回调){
var bulk=Test.collection.initializeOrderedBulkOp();
bulk.find({“\u id”:id,“readers.user”:userId}).updateOne({
“$set”:{“readers.$.someData”:1}
});
bulk.find({“\u id”:id,“readers.user”:{“$ne”:userId}}).updateOne({
“$push”:{“readers”:{“user”:userId,“someData”:1}
});
bulk.execute(函数(错误、结果){
如果(错误)回调(错误);
日志(“更新1:”);
log(JSON.stringify(result,未定义,2));
Test.findById(id,函数(err,doc){
控制台日志(doc);
回调(err);
});
});
},
//第二次替换阵列第一次更新匹配1已修改
函数(回调){
var bulk=Test.collection.initializeOrderedBulkOp();
bulk.find({“\u id”:id,“readers.user”:userId}).updateOne({
“$set”:{“readers.$.someData”:2}
});
bulk.find({“\u id”:id,“readers.user”:{“$ne”:userId}}).updateOne({
“$push”:{“readers”:{“user”:userId,“someData”:2}
});
bulk.execute(函数(错误、结果){
如果(错误)回调(错误);
日志(“更新2:”);
log(JSON.stringify(result,未定义,2));
Test.findById(id,函数(err,doc){
控制台日志(doc);
回调(err);
});
});
},
//清晰阵列
函数(回调){
Test.findByIdAndUpdate(id,
{“$pull”:{“readers”:{}},
{“新”:正确},
功能(错误、文档){
console.log('cleared:');
控制台日志(doc);
回调(err);
}
);
},
//没有数组匹配时调用了级联1内部条件
函数(回调){
log('update3:');
Test.findOneAndUpdate(
{“_id”:id,“readers.user”:userId},
{“$set”:{“readers.$.someData”:1},
{“新”:正确},
傅
    Model.findByIdAndUpdate(id,
    {
     $pull: {"readers": {user: req.user.id}},
     $push:{"readers":{user: req.user.id, someData: data}}
    },{multi:true},callback)