简体   繁体   中英

Multiple mongoose count() queries to a MongoDB

first: me -> MongoNoob and I know this has already been asked in one or the other way, but I haven't found anything specific until now. Let's say I have two Moongoose Models described like this:

var pollSchema = mongoose.Schema({
    title: String,
    choices: [{
        content: String
    }]
});
var choiceSchema = mongoose.Schema({
    poll_id: mongoose.Schema.ObjectId,
    option: Number
});

A UI shows the poll and when a user selects a choice, it is written into the choiceSchema model. Now I would like to create a 'statistic', telling me how many users selected option 1, option 2, option 3,.... I could simply fetch all choices for a poll with find and generate the statistic in server code, but if I had a million user choices, I would have to deal with an array of the same size. This cannot be right. I could however generate a query and use the count() method:

var query = Choice.find({poll_id: someId}),
query.where('option', 1);
var resultForOption1;
query.count(function(err, count)) {
    resultForOption1 = count;
});

How would I do this for multiple options and 'join' (haha) the results into an array? Since this is all asynchronous I would have nest the calls, but that is not an option for a variable number of queries.

Do I miss the wood for the trees :-)? Can somebody point me in the right direction?

BR, Daniel

You can use aggregate to do this:

Choice.aggregate(
    {$group: {_id: {poll_id: '$poll_id', option: '$option'}, count: {$sum: 1}}}
).exec(...);

This will group the choices collection docs by poll_id and option and count the occurrences of each, giving output that looks like:

{
  "result": [
    {
      "_id": {
        "poll_id": 2,
        "option": 3
      },
      "count": 1
    },
    {
      "_id": {
        "poll_id": 1,
        "option": 2
      },
      "count": 2
    },
    {
      "_id": {
        "poll_id": 2,
        "option": 2
      },
      "count": 1
    },
    {
      "_id": {
        "poll_id": 1,
        "option": 1
      },
      "count": 1
    }
  ],
  "ok": 1
}

You can then use subsequent $group and $project stages in your aggregate pipeline to further group and reshape the generated docs as needed.

If you want just iterate over the count queries and do it easy and clean you can use a lib like co or even better, async:

async.map({ "option":1 },{ "option":2 }], Choice.find, function(e, r){
    // And you continue from here
});

Another option -better in my opinion-. is to use aggregate queries . You will learn more about mongoDB and should be more efficient. In the link I send to you the first example is almost what you want to do:

询问
(source: mongodb.org )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM