1

I have a model like this :

var field = {
    createdAt: {type: Date, default: Date.now()},
    updatedAt: {type: Date, default: Date.now()},
    pic : {type: String, default: 'http://lorempixel.com/400/400/abstract/', writable: true},
    thumb : {type: String, default: 'http://lorempixel.com/100/100/abstract/', writable: true},

    name: {type: String},
    description: {type: String},
    isPublic: {type: Boolean, default: true},
    members: [{type: Schema.Types.ObjectId, ref: 'Member'}],
}

Im using this code below to get the total count of the Member's ID in members field.

Group.aggregate([
    {$match: {_id:req.params.group_id}},
    {$group: {
        _id: '$members',
        count: {$sum: 1}
    }}
], function (err, count) {
    res.send(count);
});

But it returns and empty array [] how do I get the proper count?

Thanks.

Blakes Seven
  • 49,422
  • 14
  • 129
  • 135
jofftiquez
  • 7,548
  • 10
  • 67
  • 121
  • 1
    Mongoose does not "autocast" to `ObjectId` in aggregation pipelines. You need to cast it yourself, else your `$match` matches nothing. Been asked before, let me search for the duplicate(s). – Blakes Seven Mar 08 '16 at 02:43
  • 1
    Possible duplicate of [Can't use $match with mongoose and the aggregation framework](http://stackoverflow.com/questions/14551387/cant-use-match-with-mongoose-and-the-aggregation-framework) – Blakes Seven Mar 08 '16 at 02:46
  • 1
    Also on [issue #1399](https://github.com/Automattic/mongoose/issues/1399) – Blakes Seven Mar 08 '16 at 02:47
  • So assuming that I got the working `{$match}` will this return the total number of `members`? Thanks.@BlakesSeven – jofftiquez Mar 08 '16 at 02:49
  • 1
    Lengthy related [Mongoose Aggregation does not Filter by Input Date](http://stackoverflow.com/questions/35655476/mongoose-aggregation-does-not-filter-by-input-date/35663467#35663467) – Blakes Seven Mar 08 '16 at 02:50
  • I suppose you have "two" questions really, being your actual question and the main reason for the empty result. – Blakes Seven Mar 08 '16 at 02:58
  • See also [Querying Interal Array Size](http://stackoverflow.com/questions/6722850/querying-internal-array-size-in-mongodb) – Blakes Seven Mar 08 '16 at 03:26

1 Answers1

0

Mongoose does not "autocast" to OjectId or any other schema type within the aggregation pipeline. So your operation returns nothing since it matches nothing.

Also, that would not be the approach to counting members of an array.

Better to use the $size option instead to count array members per document:

Group.aggregate([
    { "$match": { _id: ObjectId(req.params.group_id) }},
    { "$group": {
        "_id": null,
        "count": { "$sum": { "$size": "$members" } }
    }}
], function (err, count) {
    res.send(count);
});

And $group with the _id for the appropriate roll-up, or null as used here for all items in the collection.

If you wanted the "count of each distinct member" then you would process with $unwind across document(s) instead:

Group.aggregate([
    { "$match": { _id: ObjectId(req.params.group_id) }},
    { "$unwind": "$members" },
    { "$group": {
        "_id": "$members",
        "count": { "$sum": 1 }
    }}
], function (err, count) {
    res.send(count);
});
Blakes Seven
  • 49,422
  • 14
  • 129
  • 135
  • { "$group": { "_id": null, "count": { "$sum": { "$size": "$members" } } }} returns { name: 'MongoError', message: 'exception: invalid operator \'$size\'', errmsg: 'exception: invalid operator \'$size\'', code: 15999, ok: 0 } – jofftiquez Mar 08 '16 at 03:07
  • @TheGreenFoxx Which MongoDB server version do you have? `$size` has been supported since MongoDB 2.6, so it must be old. Variate on processing with `$unwind` and `null` or `$_id` even in the `$group` `_id` key. – Blakes Seven Mar 08 '16 at 03:11
  • Oooh I was using 2.4.9 I should upgrade. – jofftiquez Mar 08 '16 at 03:12
  • 1
    @TheGreenFoxx Yes you should. `$unwind` is your only approach pre 2.6. Note that just `{ "$project": { "count": { "$size": "$members" } } }` works just fine ( where supported ) if you are only doing this per document and not actually "grouping" anything. I would also advise to keep the "count" in your document via [`$inc`](https://docs.mongodb.org/manual/reference/operator/update/inc/) when adding to arrays – Blakes Seven Mar 08 '16 at 03:15
  • I think the `$inc` approach will be fine coz everytime I get a group I always needed the count. Great advice +1 – jofftiquez Mar 08 '16 at 03:18