MongoDB обновить конкретный элемент вложенного документа (массив) на основе условия?
У меня есть PostSchema, который имеет массив свойств с именем votedBy:[], это тип votedBySchema. Как ниже:
var votedBySchema = new Schema({
voteType:{
type:Boolean,default:false
},
voter:{
type:Schema.Types.ObjectId
}
});
const PostSchema = new Schema({
_authorId:{
type:Schema.Types.ObjectId,
required:true
},
title:{
type:String,
required:true
},
body:{
type:String,
},
date:{
type:Date
},
hidden:{
type:Boolean,
default:false
},
popularity:{
type:Boolean
},
votedBy:[{
type:votedBySchema,
}]
});
Теперь я запускаю запрос патча от почтальона с URL /post/:postId
Здесь я запускаю промежуточное ПО, которое проверяет, есть ли у запрашивающего пользователя действительный токен. И помещаю userObject и токен в объект req.
Далее я хочу, чтобы, если пользователь является автором сообщения, он может изменить все, что касается сообщения, но если он не является автором, то он может изменить только популярность, т.е. upVote или downVote.
Моя логика заключалась в том, что каждый голосующий должен быть зарегистрирован в массиве votedBy. лайк:
votedBy:[
{voteType:true,voter:'abcd@gmail.com'}, //upvote
{voteType:false,voter:'pqrs@gmail.com'}//downvote
]
Так как электронная почта уникальна, она может быть в состоянии только поднять или опустить такую уникальную запись на основе электронного письма в votedBy.
логический код моего маршрута:
app.patch('/post/:postId',authenticate,(req,res)=>{
console.log("[server.js]=>request ${req.method} to ${req.url}")
let body = _.pick(req.body,["title","body","popularity","hidden"])
let user = req.user;
let userId = user._id;
let postId = req.params.postId;
Post.findById(postId).then((post)=>{
let oldPost = post;//No use in code
console.log(`Found post ${post}`);
let postAuthorId = post._authorId.toString();
if(postAuthorId == userId){
post.title = body.title || post.title;//new,old
post.body = body.body || post.body;
post.hidden = body.hidden ||post.hidden;
post.update(post,{new:true}).then((postUpdated)=>{
console.log("Post Updated");
res.send(postUpdated);
});
}
else{
let voter = user.email;
console.log("\n voter is \n",voter)
let voteType = body.popularity;
//below code needs to be changed
/* post.update(
{
$set:{
'votedBy.$.voteType':voteType,
'votedBy.$.voter':voter
}
},
{
new:true
}
).then((iDontKnow)=>{
console.log('I dont know',iDontKnow);
res.send(post);
})*///Update or push the votedBy array for voter
}
});
});
Примечание. Я хочу добавить функцию голосования так же, как fb/youtube. Также предложите, если есть какой-нибудь другой способ.
1 ответ
Идея сделать это хорошо, но если бы я реализовал это, я бы сохранил userId для отображения, а не электронную почту пользователя.
В конечном итоге вы получите этот пост из внешнего интерфейса, чтобы вы могли отправлять значения из внешнего интерфейса, но это не будет хорошим методом.
post.findOneAndUpdate( { userId : 'id of user from session' }, { "votedBy.$. voteType" : "true/false"}, { upsert : true }, callback );
Поэтому сначала нужно выполнить операцию поиска, чтобы получить значение типа голосования для конкретного пользователя, а затем обновить его.
Код маршрута будет примерно таким
dbOperation.getPostData(request.body.postId, userId , (err,result)=>{
if(err){ //log the error}
else if(result!=undefined){
dbOperation.updatePost(request.body, (err,result)=>{
if(err){ //log the error}
else{
response.json({message:'update',code:200,success:true});
}
});
else{
response.json({message:'post not found',code:404,success:false});
}
});