2

I am using mongoose 4.6.3.

I have the following schema :

var mongoose = require('mongoose');
var User = require('./User');

var TicketSchema = new mongoose.Schema({
    user : { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
},
{
    timestamps: true
});

var DrawSchema = new mongoose.Schema({
  ...
  max_ticket_per_user : { type : Number, required: true },
  tickets: [TicketSchema]
});

module.exports = mongoose.model('Draw', DrawSchema);

How can I count the embedded documents of a certain User ObjectId(user field in TicketSchema) in a Draw's tickets(tickets field in DrawSchema) ? I want to count the tickets of a user for a single draw.

Would it be better to change my schema design ?

Thanks

2 Answers 2

4

You can use the aggregation framework taking advantage of the $filter and $size operators to get the filtered array with elements that match the user id and its size respectively which will subsequently give you the count.

For an single draw, consider adding a $match pipeline operator as your initial step with the _id query to filter the documents in the collection.

Consider running the following aggregation pipeline to get the desired result:

Draw.aggregate([
    { "$match": { "_id": drawId } },
    {
        "$project": {
            "ticketsCount": {
                "$size": {
                    "$filter": {
                        "input": "$tickets",
                        "as": "item",
                        "cond": { "$eq": [ "$$item.user", userId ] }
                    }
                }
            }
        }
    }
]).exec(function(err, result) {
    console.log(result);
});
Sign up to request clarification or add additional context in comments.

4 Comments

Great answer. I get the information I need but I only want to aggregate on a draw with a given id.
what I get as a response is all the draws id with their count for the userId. I only want to aggregate on a single draw id
@AlexB You'd need a $match pipeline query to filter your documents, as I've shown in the update above.
FWIW, Most cloud based Mongodb platforms, such as every cloud based solution provided by Heroku, doesn't support mongo version 3.4 yet, and hence the $filter command won't work
2

You can pass the .count() deep parameters like any other query object:

Draw.count({'tickets.user._id' : userId}, console.log);

Make sure the userId variable is an ObjectId. If it's a string, do this:

const ObjectId = require('mongoose').Types.ObjectId;
let userId = new ObjectId(incomingStringId);

1 Comment

This wouldn't work for a specific draw. I will try adding "_id" : drawId

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.