Обновление двойного вложенного массива MongoDB
Рассмотрим эту схему:
let userSchema = new mongoose.Schema({
id: String,
displayName: String,
displayImage: String,
posts: [
{
url: String,
description: String,
likes: [String],
comments: [
{ content: String, date: String, author: { id: String, displayName: String, displayImage: String } }
]
}
]
});
Я могу удалить определенный элемент из массива комментариев, используя этот запрос
controller.deleteComment = (req, res, next) => {
User.findOneAndUpdate(
{ id: req.query.userid, 'posts._id': req.params.postid, },
{
$pull: {
'posts.$.comments': { _id: req.body.commentID },
}
}
)
.exec()
.then(() => {
res.send('deleted');
})
.catch(next);
};
В любом случае, я могу ОБНОВИТЬ элемент внутри массива комментариев, используя $set
оператор? Мне нужно изменить содержимое комментария на основе его идентификатора комментария.. что-то вроде этого:
controller.editComment = (req, res, next) => {
User.findOneAndUpdate(
{ id: req.query.userid, 'posts._id': req.params.postid, 'comments._id':req.body.commentID },
{
$set: {
'posts.$.comments': { content: req.body.edited },
}
}
)
.exec()
.then(() => {
res.send('deleted');
})
.catch(next);
};
Это... очевидно не работает, но мне интересно, есть ли способ, которым я могу это сделать?
ОБНОВЛЕНИЕ Согласно предложениям ниже, я делаю следующее, чтобы управлять только одной Схемой. Это работает, однако обновляются только комментарии первого поста, независимо от того, какие комментарии я редактирую. Я проверил, и обратные документы всегда верны. Там должно быть проблемы с doc.save()
метод.
controller.editComment = (req, res, next) => {
User.findOne(
{ id: req.query.userid, 'posts._id': req.params.postid },
{ 'posts.$.comments._id': req.body.commentID }
)
.exec()
.then((doc) => {
let thisComment = doc.posts[0].comments.filter((comment) => { return comment._id == req.body.commentID; });
thisComment[0].content = req.body.edited;
doc.save((err) => { if (err) throw err; });
res.send('edited');
})
.catch(next);
};
2 ответа
Я не знаю простой (или даже жесткий:P) способ добиться того, что пытаются сделать. В монго манипулирование сравнительно сложно в двухуровневых массивах и, следовательно, его лучше избегать.
Если вы по-прежнему открыты для изменений схемы, я бы предложил вам создать другую схему для комментариев и ссылаться на эту схему внутри пользовательской схемы.
Таким образом, ваша схема комментариев будет выглядеть так:
let commentSchema = new mongoose.Schema({
content: String,
date: String,
author: {
id: String,
displayName: String,
displayImage: String
}
});
И ваша пользовательская схема должна выглядеть так:
let userSchema = new mongoose.Schema({
id: String,
displayName: String,
displayImage: String,
posts: [{
url: String,
description: String,
likes: [String],
comments: [{
type: Schema.Types.ObjectId,
ref: 'comment' //reference to comment schema
}]
}]
});
Таким образом, ваши манипуляции с данными будут намного проще. Вы можете заполнить комментарии при получении пользовательского документа. И обратите внимание, насколько просты операции обновления / удаления, учитывая, что вы уже знаете _id комментариев, которые хотите обновить.
Надеюсь, вы найдете этот ответ полезным!
controller.editComment = (req, res, next) => {
User.findOneAndUpdate(
{ id: req.query.userid, 'posts._id': req.params.postid, 'comments._id':req.body.commentID },
{
$push: {
'posts.$.comments': { content: req.body.edited },
}
}
)
.exec()
.then(() => {
res.send('deleted');
})
.catch(next);
};