Nodejs中如何对用mongoose对内嵌文档进行类似upsert的操作呢?
Nodejs中如何对用mongoose对内嵌文档进行类似upsert的操作呢?
Schema = {
uid:{type:ObjectId},
reply:[]
}
我想在reply里push每一个人的对话集合
reply:[
{
user_id:123,
commnet:[]
},
{
user_id:456,
comment:[]
}
]
如果我想在user_id:789的comment里面push一条对话内容
{
user_id:789,
comment:[
{
//内容
}
]
}
得先判断user_id:789的对话集合是否存在,如果不存在,创建它
find()该文档后用遍历可以实现,但是太耗时
var exists = false;
var index;
for(var i in reply){//reply为find()后返回的doc.reply
if(reply[i].user_id == '789'){
exists = true;
index = i;
return;
}
}
if(exists){//如果存在
reply[i].comment.push({//内容})
}else{//如果不存在
reply.push({
user_id:789,
comment:[
{
//内容
}
]
})
}
很明显,这样做太耗时,而且繁杂,有没有更简便的方法实现上面的东西呢?
要在Node.js中使用Mongoose对内嵌文档进行类似upsert
的操作,可以通过使用findOneAndUpdate
方法来简化流程。这种方法可以在查询到文档后自动插入或更新指定的内嵌文档,从而避免了手动遍历和判断的过程。
假设我们有一个Schema定义如下:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const replySchema = new Schema({
user_id: { type: Number, required: true },
comment: [{ content: String }]
});
const mainSchema = new Schema({
uid: { type: mongoose.Schema.Types.ObjectId },
reply: [replySchema]
});
const MainModel = mongoose.model('Main', mainSchema);
现在我们需要在reply
数组中添加一个新用户(例如user_id: 789
)的评论。我们可以使用findOneAndUpdate
方法来实现这个操作:
async function addCommentToUser(uid, user_id, commentContent) {
const filter = { uid: uid };
const update = {
$push: {
reply: {
$each: [
{
user_id: user_id,
comment: [{ content: commentContent }]
}
],
$position: 0 // 可以选择插入的位置
}
}
};
const options = {
upsert: true, // 如果没有找到匹配的文档,则创建一个新的
new: true, // 返回更新后的文档
runValidators: true // 运行验证器
};
try {
const result = await MainModel.findOneAndUpdate(filter, update, options);
console.log(result); // 输出更新后的文档
} catch (error) {
console.error(error);
}
}
// 使用示例
addCommentToUser('some-uid', 789, 'Hello World!');
在这个例子中,$push
操作符用于向 reply
数组中添加新的文档。$each
和 $position
用于指定要插入的具体位置。upsert
设置为 true
表示如果没有找到匹配的文档,则会创建一个新的。
这样,我们就能够高效地完成对内嵌文档的upsert
操作,而不需要手动遍历和检查是否存在。
you
http://cnodejs.org/topic/50a60955637ffa4155faf861 我本来一直都是像我那样遍历的,我昨天晚上看你的帖子,看到省时多了,立马就想把自己的前面写的都改了,但是一直没弄好,aggregate只能获取数据,不能对数据进行操作保存啊
求指点呐
眼看小弟的网站就要上线了,这点问题还没解决,求大神们指导啊
要在Mongoose中对内嵌文档执行类似upsert
的操作,你可以使用findOneAndUpdate
方法,并结合$push
和$elemMatch
操作符。这样可以避免显式的查找和更新过程,从而提高效率。
以下是一个示例代码,展示了如何实现上述需求:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ReplySchema = new Schema({
user_id: { type: String, required: true },
comment: [{ text: String }] // 假设comment是一个对象数组,每个对象有一个text字段
});
const MessageSchema = new Schema({
uid: { type: Schema.Types.ObjectId },
reply: [ReplySchema]
});
const Message = mongoose.model('Message', MessageSchema);
async function updateReply(uid, user_id, comment) {
const filter = {
uid,
reply: { $elemMatch: { user_id } }
};
const update = {
$push: {
'reply.$.comment': comment
}
};
const options = {
upsert: true,
new: true
};
try {
const result = await Message.findOneAndUpdate(filter, update, options);
console.log(result);
} catch (error) {
console.error(error);
}
}
updateReply('some-uid', '789', { text: 'Hello World' });
在这个示例中:
filter
用于定位包含指定user_id
的reply
。update
使用$push
操作符来向匹配的reply
中的comment
数组添加新的评论。options
设置upsert: true
表示如果找不到匹配的文档,则插入一个新的文档。new: true
确保返回更新后的文档,而不是原始文档。
这种方法比手动遍历和查找更高效且简洁。