I know i have to use some
but for some reason i cant seem to get it right. i have a collection in my mongodb database of posts. each post has an array of objects named "likes" that references the users that liked this post. so in my backend i want to check if the user exists in the likes array of the post. if it does not exist then like the post, else return with an appropriate message on my react frontend. The code i will include always returns false from some
so a user can like a post infinite times.
exports.postLike = async (req, res, next) => {
const postId = req.query.postId;
const userId = req.query.userId;
console.log('postId: ' + postId);
try{
const post = await Post.findById(postId).populate('creator').populate('likes');
const user = await User.findById(userId);
if (!post.likes.some(post => post._id === user._id)){
post.likes.push(user);
console.log('liked a post');
const result = await post.save();
res.status(200).json({ message: 'Post liked!', post: result });
} else {
console.log('Post already liked!');
res.status(200).json({ message: 'Post already liked!', post: post });
}
}catch (err) {
if (!err.statusCode) {
err.statusCode = 500;
}
next(err);
}
};
i clearly haven't understood, yet, how some
works so if you can help that would be great. also if you have any other solution that would be good in this case then please post it. i tried some random codes with indexOf and includes for checking but it didn't work either. i am not sure which is the right way to check if the user object is included in the "likes" array of objects. i would prefer not to write any function of my own to check this, i want to do it using an existing function/method provided by javascript.
2 Answers 2
Going to offer a different route here. You are fetching all the data including a join to the creator and likes just to add a like to the collection. This is a little wasteful and can be achieved by just doing an update
and use $addToSet which will add the like if it does not exist.
You then just check nModified
in the result to know if it was added or not. So you can have:
const result = await Post.updateOne(
{
id: 1
},
{
$addToSet: {
likes: {
userId: mongoose.Types.ObjectId(req.query.userId)
}
}
}
);
console.info(result.nModified === 1);
Alternatively, you can use some
as follows using ===
to compare type and value:
posts.likes.some(like => like.userId.toString() === req.query.userId)
-
1just a bit change in the names but thanks!! this actually worked. i will also check out the update option. seems like you have a really good point!
post.likes.some(like => like._id.toString() === userId)
gevor– gevor2019年12月02日 17:35:47 +00:00Commented Dec 2, 2019 at 17:35 -
No prob, best of luck with the restSamuel Goldenbaum– Samuel Goldenbaum2019年12月02日 17:56:50 +00:00Commented Dec 2, 2019 at 17:56
MongoDB.ObjectId
is a wrapper around a primitve, just like Number
or Boolean
. And just like
new Boolean(true) === new Boolean(true)
will be false, your comparison will fail too. You have to take out the primitive for comparison:
post._id.valueOf() === user._id.valueOf()
-
some
still returns always falsegevor– gevor2019年12月02日 16:09:54 +00:00Commented Dec 2, 2019 at 16:09 -
Are you sure that
post.likes
actually contains an entry with a matching_id
?Jonas Wilms– Jonas Wilms2019年12月02日 16:10:36 +00:00Commented Dec 2, 2019 at 16:10 -
yes. i can see the object of the user reference in my database. in mongodb compass and i can also print and see the post.likes array of objects. both contain the usergevor– gevor2019年12月02日 16:12:30 +00:00Commented Dec 2, 2019 at 16:12
_id
? Is it a string or aMongoDB.ObjectId
?MongoDB.ObjectId
likes
is in a separate collection correct?