【问题标题】:MongoDB distinct aggregationMongoDB 不同的聚合
【发布时间】: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 answerMongo's documentation):db.collectionName.aggregate([{$group: {_id: null, uniqueValues: {$addToSet: "$fieldName"}}}])

标签: mongodb distinct


【解决方案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'}}}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-21
    • 2018-05-25
    • 1970-01-01
    • 2016-08-16
    相关资源
    最近更新 更多