我如何在mongodb聚合中同时计算文档总数和分组计数?

时间:2019-12-20 03:58:03

标签: mongodb aggregation

我在mongodb集合中有一个名为visitorsSession的数据集,例如

{ip : 192.2.1.1,country : 'US', type : 'Visitors',date : '2019-12-15T00:00:00.359Z'},
{ip : 192.3.1.8,country : 'UK', type : 'Visitors',date : '2019-12-15T00:00:00.359Z'},
{ip : 192.5.1.4,country : 'UK', type : 'Visitors',date : '2019-12-15T00:00:00.359Z'},
{ip : 192.8.1.7,country : 'US', type : 'Visitors',date : '2019-12-15T00:00:00.359Z'},
{ip : 192.1.1.3,country : 'US', type : 'Visitors',date : '2019-12-15T00:00:00.359Z'}

我正在使用此mongodb聚合

[{$match: {
  nsp : "/hrm.sbtjapan.com",
  creationDate : {
  $gte: "2019-12-15T00:00:00.359Z",
  $lte: "2019-12-20T23:00:00.359Z"
 },
 type : "Visitors"
 }}, {$group: {
 _id : "$country",
 totalSessions : {
   $sum: 1
  }

  }}, {$project: {
    _id : 0,
    country : "$_id",
    totalSessions : 1
   }}, {$sort: {
  country: -1
 }}]

aggregation以上,我得到了这样的结果

[{country : 'US',totalSessions  : 3},{country : 'UK',totalSessions  : 2}]

但是我也吸引了所有访问者,以及诸如totalVisitors : 5之类的结果 我如何在mongodb aggregation中做到这一点?

2 个答案:

答案 0 :(得分:2)

您可以使用$facet聚合阶段来一次计算总访问者以及按国家/地区划分的访客

db.visitorsSession.aggregate( [
  {
      $match: {
          nsp : "/hrm.sbtjapan.com",
          creationDate : {
              $gte: "2019-12-15T00:00:00.359Z",
              $lte: "2019-12-20T23:00:00.359Z"
          },
          type : "Visitors"
      }
  },
  { 
      $facet: {
            totalVisitors: [
                { 
                    $count: "count" 
                }
            ],
            countrySessions: [
                {
                    $group: {
                        _id : "$country", 
                        sessions : { $sum: 1 }
                    }
                },
                { 
                    $project: { 
                        country: "$_id", 
                        _id: 0, 
                        sessions: 1 
                    } 
                }
            ],
      }
  },
 { 
      $addFields: { 
          totalVisitors: { $arrayElemAt: [ "$totalVisitors.count" , 0 ] },
      } 
  }
] )

输出:

{
        "totalVisitors" : 5,
        "countrySessions" : [
                {
                        "sessions" : 2,
                        "country" : "UK"
                },
                {
                        "sessions" : 3,
                        "country" : "US"
                }
        ]
}

答案 1 :(得分:0)

使用两个查询可能会更好。

要保存聚合后的两次数据库往返,可以使用IMO有点冗长(如果文档很大,则可能会花费很少)来计数文档。

想法:是在顶部放置一个$group来计数文档并使用$push $$ROOT 。然后在其他比赛/过滤器操作$unwind之前创建原始文档数组。

db.collection.aggregate([
  {
    $group: {
      _id: null,
      docsCount: {
        $sum: 1
      },
      originals: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $unwind: "$originals"
  },
  { $match: "..." }, //and other stages on `originals` which contains the source documents
  {
    $group: {
      _id: "$originals.country",
      totalSessions: {
        $sum: 1
      },
      totalVisitors: {
        $first: "$docsCount"
      }
    }
  }
]);

示例O / P: Playground Link

[
  {
    "_id": "UK",
    "totalSessions": 2,
    "totalVisitors": 5
  },
  {
    "_id": "US",
    "totalSessions": 3,
    "totalVisitors": 5
  }
]