0

so I'm trying to do a simple Thumbs Up system for an App I'm working on, but I'm having issues pushing the User ID to the likes Array. Heres what my code looks like:

Room Schema

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const classroomSchema = Schema({
    clName: String,
    clPosts: [{
        title: String,
        mssg: String,
        date: String,
        imageurl: String,
HERE==> likes: [{type: Schema.Types.ObjectId, ref: 'User'}] 
    }]
})

const Classroom = mongoose.model('Classroom', classroomSchema)
module.exports = Classroom

router

router.put('/put/classroom/post/like/:id', (req, res, next) => {
    var data = data = req.body
    Classroom.findByIdAndUpdate(
        {
            _id: req.params.id,
            "clPosts": { _id: data.post }
        },
        { $push: { "clPosts.$[outer].likes": [data.user] } },
        { "arrayFilters": [{ "outer._id": data.post }] }
    ).then((room) => {
         console.log("Done"); 
         res.json(room);
    }).catch(next)
})

I've tried following other suggestions here on SO but I'm not sure if I have something configured incorrectly or there is a better way of pushing an object into a nested array.

The Basic setup is, there is a Classroom Collection holding Classroom Objects. within The Classroom, there is posts Object Array, and inside that, a likes Array. The idea is whenever someone Likes the post, it saves the ObjectID of that user into the array, which I then use to count how many likes, etc...

If any more detail is needed please let me know, MongoDB doesn't have good documentation on nesting arrays.

2 Answers 2

1

clPosts is a subdocument. You query posts by _id -> "clPosts": { _id: data.post } but I believe, the query should look like this: "clPosts._id": { _id: data.post_id }

Since you use mongoose, you can do this:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const ClassRoomPostsSchema = new Schema({
    title: String,
    mssg: String,
    date: String,
    mageurl: String,
    likes: [] // you will push ids here or else, if you need to store more data, e.g. date/time when like was given, create a schema for Likes e.g. likes: [likeSchema.schema]
})

const ClassRoomSchema = new Schema({
    clName: String,
    clPosts: [ClassRoomPostsSchema.schema]
})

Then in your code:

router.put('/put/classroom/post/like/:id', (req, res, next) => {
  ClassRoom.findOne({_id: req.params.id}, function(err, room) {
    if (err) return next(err);

    if (!room) return res.status(404).send('Classroom not found');

    //Find a post by id
    let post = ClassRoom.clPosts.id(data.post); // -> data.post_id

    if (!post) return res.status(404).send('Post not found');

    // Here you can push ids, but what is the idea behind? Maybe it makes more sense to count likes or push Like schemas (subdocument) to the array, e.g. post.likes.push(new Like(data));        
    post.likes.push();

    room.save(function(err) {
      if (err) return serverValidationError(req, res, err);
      res.status(200).send('success');
    });
  });      
})
Sign up to request clarification or add additional context in comments.

1 Comment

Hi thanks for the response, i realize i was putting the _id in the wrong place, but ive decided to go with your sugestion for creating a new schema for the likes, i hadnt thought about adding extra data to the like. i no longer need to push an object into a nested Array
1

Try this way

Classroom.findByIdAndUpdate(
        {
            _id: req.params.id,
            "clPosts._id": data.post
        },
        { $push: { "clPosts.$.likes": [data.user] } }
    ).then((room) => {
         console.log("Done"); 
         res.json(room);
    }).catch(next)

1 Comment

Hi thanks for the response, i realize i was putting the _id in the wrong place, but after trying your solution i continue to get the error: [ERROR] The positional operator did not find the match needed from the query.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.