this question is related to the same problem exposed here (a solution has been added to that one) but I've re-designed my algorithm and I come to you with a quite different question.
What is this about ?
const mongoose = require('mongoose');
const sauceSchema = mongoose.Schema({
userId: {type:String},
name: {type:String, required:true},
manufacturer:{type:String, required:true},
description:{type:String, required:true},
mainPepper: {type:String, required:true},
imageUrl:{type:String, required:true},
heat: {type:Number, required:true},
likes: {type:Number},
dislikes : {type:Number},
usersLiked : {type:["String <userId>"]},
usersDisliked: {type:["String <userId>"]},
});
module.exports = mongoose.model('sauce', sauceSchema);
the above model has, at the end, 2 arrays. Those two as mentioned, store userId's of people who liked or disliked a particular sauce product.
On the same model, just above the two arrays, we find two "counters" : likes and dislikes.
this model has been made with Mongoose and the collection of sauces is stored on MongoDB.
What is your problem ?
I have to make a route in my controllers for this like/dislike system and in order to do that I would like to access the two arrays length and set the numbered value of that length as the likes/dislikes value.
I read a dozen of posts, tried several options but either I'm sent back to an undefined, or I'm being said nothing.
What did you try so far ?
this is the route code with only the 'like' case for clarity purpose :
exports.likeSauce = (req,res,next) =>{
const liker = req.body.userId;
let likeStatus = req.body.like;
if(likeStatus === 1){
sauce.updateOne({_id:req.params.id}, {$push:{usersLiked:liker}, $inc:{likes:totalLiked}})
.then(()=>res.status(201).json({message:'you liked this sauce'}))
.catch(error=>res.status(400).json({error}))
}else{}
- liker = id of the user who liked
- likeStatus = a value sent by the front in a request and that can be 1(like) or 0(none) or -1(dislike).
- usersLiked = the array of strings from the model that stores likers id's.
- totalLiked = it would ideally be the usersLiked.length numbered value that would be passed as the likes 'counter' value and stored as a number in the data base.
For totalLiked, I tried various things as earlier mentioned but came down to two fairly similar lines :
let totalLiked = sauce.findOne([{$match:{_id:req.params.id}}, {$project:{usersLiked:{$size:'$usersLiked'}}}])
//or//
let totalLiked = sauce.aggregate([{$match:{_id:req.params.id,usersLiked:{$size:'$usersLiked'}}}])
One thing to mention about an element of the route:
sauce.updateOne({_id:req.params.id}, {$push:{usersLiked:liker}, $inc:{likes:totalLiked}})
I got errors regarding the 'undefined' status of 'totalLiked', so I chose to put the $inc at the end of the pipeline in order to 'wait' for the liker to be added to the array in order to get a defined element that could return a workable length. But maybe I did mix things up here...
Thank you for reading my post and for any help you may be able to prove !