Neetigya Chahar
Neetigya Chahar

Reputation: 693

Mongoose, $pull an element from nested array and update document based on the presence of the element

I am working on a mongoose schema similar to this:

const actionSchema = {
    actions: {
        type: [{
            actionName: {
                type: String,
                required: true
            },
            count: {
                type: Number,
                default: 0,
                required: true
            },
            users: [{
                type: Schema.Types.ObjectId,
                ref: 'User'
            }]
        }]
    }};

It is a nested schema of a post schema. Here, actions are dynamically generated and number of people does that action are maintained by count and their identity is maintained by users array.

As you see, actions is an array of objects which further contain users array. I want to check if a provided user id is present in any of the action object and then remove it from array and also reduce the count.

Being totally new to mongoose and mongodb, one simple way I see is to find the post using Post.findById() which has to be updated, run js loops, update the post and call .save(). But it can be very costly when users array has thousands of user ids. I tried .update() but can't understand how to use it in this case.

How about adding a method to the Post Model (like postSchema.methods.removeUserAction)? This gives access to document from this and allows to update the document and thus call .save(). Does it loads the full document to the client node application?

So please suggest the right way. Thank you.

Upvotes: 0

Views: 219

Answers (1)

Grey
Grey

Reputation: 529

You should simplify your model, for example

// Model - Actions Model

const actionSchema = {
   actionName: {
       type: String,
       required: true
   },
   user: {
       type: Schema.Types.ObjectId,
       ref: 'User'
   }
};

And you can easily get the total actions via Model.count(), get specific action count with Model.count({ actionName: 'action name'}), and removing entries with Model.delete(condition). Unless there's a reason why you have it modeled this way.

Upvotes: 1

Related Questions