MongoDB 不同的聚合

Posted

技术标签:

【中文标题】MongoDB 不同的聚合【英文标题】:MongoDB distinct aggregation 【发布时间】:2013-04-28 10:21:02 【问题描述】:

我正在查询每个州的邮政编码最多的城市:

db.zips.distinct("state", db.zips.aggregate([ 
     $group:
       _id: 
           state: "$state", 
           city: "$city" 
         ,
        numberOfzipcodes:  
           $sum: 1
         
      
    , 
     $sort: 
        numberOfzipcodes: -1
         
      
  ])
)

查询的聚合部分似乎工作正常,但是当我添加 distinct 时,我得到一个空结果。

这是因为我在 id 中有状态吗?我可以做类似distinct("_id.state 的事情吗?

【问题讨论】:

对于那些寻找如何使用 Mongo 的聚合来获得不同值的人,试试这个(灵感来自 dam1's answer 和 Mongo's documentation):db.collectionName.aggregate([$group: _id: null, uniqueValues: $addToSet: "$fieldName"]) 【参考方案1】:

Distinct 和聚合框架不可互操作。

你只是想要:

db.zips.aggregate([ 
    $group:_id:city:'$city', state:'$state', numberOfzipcodes:$sum:1, 
    $sort:numberOfzipcodes:-1,
    $group:_id:'$_id.state', city:$first:'$_id.city', 
              numberOfzipcode:$first:'$numberOfzipcodes'
]);

【讨论】:

@alex23 Distinct 是一个完全不同的命令,它返回一个不同值的数组。与聚合框架完全不兼容 这是我之前的查询,但我需要获取每个州的不同城市而不是州 @Lemonio 重新添加了城市,现在应该会在每个州的每个城市中释放拉链 @sammaye 我认为这正是我以前所拥有的?我只想要每个州的拉链最多的城市,这就是我试图做不同的原因。这样我就得到了每个州的所有城市,这是我之前的查询 @Lemonio 好的,你需要做第二组,编辑,编辑:修复了一些其他错误编辑:等等【参考方案2】:

您可以将$addToSet 与聚合框架一起使用来计算不同的对象。

例如:

db.collectionName.aggregate([
    $group: _id: null, uniqueValues: $addToSet: "$fieldName"
])

或扩展以将您的唯一值放入适当的列表而不是空 _id 记录中的子文档:

db.collectionName.aggregate([
     $group: _id: null, myFieldName: $addToSet: "$myFieldName",
     $unwind: "$myFieldName" ,
     $project:  _id: 0 ,
])

【讨论】:

不是一个通用的解决方案,如果每个结果有大量唯一的邮政编码,这个数组会非常大。问题是获取每个州的大多数邮政编码的城市,而不是获取实际的邮政编码。如果给定城市有 10,000,000 个邮政编码,会发生什么? 刚刚看到这一点,它根本不会计算不同的对象,而是将对象明确地放入一个数组中,不仅如此,而且=== 上的区别并不总是一个好的主意。相反,您可能希望对不同的值进行分组,计算该值存在的次数,此时您可以轻松添加一个阶段以将其总结为唯一对象的数量。作为一种计数方法,这在内存、资源和处理器方面效率非常低。 如果它为 OP 提供了一个实际的答案,而不仅仅是 group/addtoSet 使用的语法的一般示例,这可能是一个更好的答案。 似乎 pymongo 不支持它..【参考方案3】:

SQL 查询:(分组方式和不同的计数)

select city,count(distinct(emailId)) from TransactionDetails group by city;

等效的 mongo 查询如下所示:

db.TransactionDetails.aggregate([ 
$group:_id:"CITY" : "$cityName",uniqueCount: $addToSet: "$emailId",
$project:"CITY":1,uniqueCustomerCount:$size:"$uniqueCount"  
]);

【讨论】:

这个解决方案更清晰,只选择总数。【参考方案4】:

您可以在单个数组上调用$setUnion,它还可以过滤欺骗:

 $project: Package: 1, deps: '$setUnion': '$deps.Package'

【讨论】:

以上是关于MongoDB 不同的聚合的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB聚合在Java中具有不同的价值?

MongoDB $geoNear 聚合管道(使用查询选项和使用 $match 管道操作)给出不同的结果

如何使用聚合 MongoDB 查找具有两列的不同字段

Spring Mongo 聚合查询以从 MongoDB 获取不同的国家名称和国家代码

Mongodb聚合:从键值对象返回不同值的计数

MongoDB聚合组和计数字符串