mongodb multiple $group in single query

时间:2018-07-25 04:47:31

标签: mongodb mongodb-query aggregation-framework

I have documents similar to this stored in mongodb :

{
    "_id" : ObjectId("----"),
    "status" : "pending",
    "user" : "huSWFekrPkw_xwtqDueAm4j4tHiuPJf3",
    "type" : "inMemory",
    "question" : "Hello, How are you?",
    "intent" : "Greeting",
    "createdAt" : ISODate("2018-07-24T06:33:59.399Z"),
    "updatedAt" : ISODate("2018-07-24T06:33:59.399Z"),
}
{
    "_id" : ObjectId("----"),
    "status" : "trained",
    "user" : "huSWFekrPkw_xwtqDueAm4j4tHiuPJf3",
    "type" : "inMemory",
    "question" : "Holla",
    "intent" : "Greeting",
    "createdAt" : ISODate("2018-07-25T06:33:59.399Z"),
    "updatedAt" : ISODate("2018-07-25T06:33:59.399Z"),
}
{
    "_id" : ObjectId("----"),
    "status" : "trained",
    "user" : "huSWFekrPkw_xwtqDueAm4j4tHiuPJf3",
    "type" : "inMemory",
    "question" : "want to talk with agent?",
    "intent" : "Agent",
    "createdAt" : ISODate("2018-07-26T06:33:59.399Z"),
    "updatedAt" : ISODate("2018-07-26T06:33:59.399Z"),
}

Aggregation pipelines I want :

  1. $group on intent
  2. $group on status
  3. On the basis of the result of these two groups, I want to filter how many are pending and trained for every particular Intent. Like forGreeting intent, I have 2 pending document and 1 trained document.
  4. Later I also want, How many documents for Greeting intent in today, last 7 days or last month.

So the final document will be something looks like :

{
    "intent" : "Greeting",
    "status_pending" : 1,
    "status_trained" : 2,
    "last_day" : 1,
    "last_seven_day" : 3,
    "last_month" : 7
}
{
    "intent" : "Agent",
    "status_pending" : 1,
    "status_trained" : 1,
    "last_day" : 1,
    "last_seven_day" : 2,
    "last_month" : 3
}

2 个答案:

答案 0 :(得分:1)

您可以为每个$push使用$groupintent的所有日期和状态。然后,您可以使用$filter$size来计算每个过滤器有多少个项目:

db.col.aggregate([
    {
        $group: {
            _id: "$intent",
            statuses: { $push: "$status" },
            dates: { $push: "$createdAt" },
        }
    },
    {
        $project: {
            _id: 0,
            intent: "$_id",
            status_pending: {
                $size: { $filter: { input: "$statuses", as: "s", cond: { $eq: [ "$$s", "pending" ] } } }
            },
            status_trained: {
                $size: { $filter: { input: "$statuses", as: "s", cond: { $eq: [ "$$s", "trained" ] } } }
            },
            last_day: {
                $size: { $filter: { input: "$dates", as: "d", cond: { $gt: [ "$$d", new Date(new Date().setDate(new Date().getDate()-1)) ] } } }
            },
            last_seven_day: {
                $size: { $filter: { input: "$dates", as: "d", cond: { $gt: [ "$$d", new Date(new Date().setDate(new Date().getDate()-7)) ] } } }
            },
            last_month: {
                $size: { $filter: { input: "$dates", as: "d", cond: { $gt: [ "$$d", new Date(new Date().setDate(new Date().getDate()-30)) ] } } }
            },
        }
    }
])

答案 1 :(得分:1)

您也可以尝试

db.getCollection('collectionName').aggregate([
{$group:{
    _id: "$intent",
    "status_pending": {$sum: {$cond: [{ $eq: ["$status", "pending"]}, 1,0 ]}},
    "status_trained": {$sum: {$cond: [{ $eq: ["$status", "trained"]}, 1,0 ]}},
    "last_day": { $sum: { $cond: [{$gt: [ "$createdAt", new Date(new Date().setDate(new Date().getDate()-1)) ]},1,0] } },
    "last_seven_day": { $sum: { $cond: [{$gt: [ "$createdAt", new Date(new Date().setDate(new Date().getDate()-7)) ]},1,0] } },
    "last_month": { $sum: { $cond: [{$gt: [ "$createdAt", new Date(new Date().setDate(new Date().getDate()-30)) ]},1,0] } }
  }
 }
])