MongoDB Aggregate & Grouping Issue in MeteorJS

2020-04-30 03:27发布

Using MongoDB in Meteor JS, how do you use Meteor Aggregate properly?

The intended result is to return grouped users by their userId and sum up a boolean field called "progressState" (true/false).

For example the document can have:

user 001 - true
user 001 - false
user 001 - true
user 003 - false
user 005 - true

but the intended result would be:

user 001: 2 true
user 003: 0 true
user 005: 1 true
etc..

My attempt gives the following error:

"exception: FieldPath field names may not start with '$'."

Here is my Meteor Code:

Meteor.publishComposite('completedLB', {
    find: function() {
        return userCompleted.aggregate([
            {
                $match: {
                    "progressState": "true"
                }
            },
            {
                $group: {
                    "_id": "$userId",
                    "count": {
                        "$sum": "$progressState"
                    }
                }
            },
            {
                $sort : {
                    "$progressState": -1
                }
            }
        ]);
    }
});

1条回答
来,给爷笑一个
2楼-- · 2020-04-30 03:42

If you are using the meteor hacks aggregate package to implement an .aggregate() command on your collection, then it will only just return an array in response. So you need to work that into a form of a published collection:

Meteor.publish("completedLB,function() {
    var self = this;

    var results = userCompleted.aggregate([
        { "$match": { "progressState": true } },
        { "$group": {
            "_id": "$userId",
             "progressState": { "$first": "$progressState" },
             "count": { "$sum": 1 }
        }},
        { "$sort": { "_id": 1 } }
    ]);

    _.each(results,function(result) {
        self.added("client_collection_name",Random.id(), {
            userId: result._id,
            progressState: result.progressState,
            count: result.count
        });
    });
    self.ready();
});

Or to include the false counts as your suggested output suggests itself:

        { "$group": {
            "_id": "$userId",
             "progressState": { "$first": true },
             "count": { "$sum": { "$cond": ["$progressState", 1,0] }
        }},
        { "$sort": { "_id": 1 } }

As the pipeline with a $cond evaluation to convert to numeric.

Where in the basic aggregation you are just "totalling" the matched results and of course the $sort refers to a field present in the output, which by your example would be the "userId" value now in the _id key from aggregation, but could also be "count" to order by the total count if wanted.

That part was producing the error, as $sort is a present field and not a field value with $ notation.

But of course to publish as a client accessible collection you need to replace the actual _id with something expected. So random id generation works here, as does the inclusion of the other fields.

For a bit more detail, and also an alternate to the "hacks" package that just works with a vanilla installation, there is also this answerby myself that has a complete listing as an example.

查看更多
登录 后发表回答