对mongo和rails进行分组查询

时间:2012-05-17 16:52:29

标签: ruby-on-rails mongodb mongomapper database

我有一张带有以下结构的痕迹表  id | country_iso | object_id | created_at
 每个对象可以包含一个或多个国家/地区的许多条目。我需要弄清楚每个国家现在有多少物体  我不能只按country_iso对它进行分组,因为在这种情况下,我会获得每个国家/地区的条目数,但不包括对象数。
 我无法通过country_iso和object_id对其进行分组,因为在这个时间我将获得每个国家/地区中每个对象的条目数。

所以,似乎我必须得到每个对象的最后一个条目,然后按国家分组并获得数量。此外,我需要避免最后一个条目的country_iso等于null的情况。因此,如果object的最后一个条目为null,我们必须在最后一个条目之前获得条目(因此,最新的非null country_iso)。

示例:

1 | US   | 1 | 25.02.02  
2 | null | 1 | 26.02.02  
3 | UK   | 2 | 25.02.02  
4 | UK   | 3 | 25.02.02  
5 | UK   | 4 | 25.02.02  
6 | US   | 4 | 26.02.02  `  

结果将是

US | 2  
UK | 2

提前感谢任何想法 P.S。:请注意,有很多数据(超过10万个对象,每个超过10个条目),并且它位于远程服务器上。所以,我无法获取数据,并以某种方式在主服务器上使用ruby重新计算它们。

3 个答案:

答案 0 :(得分:1)

您需要map-reduce或更短的群组版本。

http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group

http://api.mongodb.org/ruby/current/Mongo/Collection.html#group-instance_method

https://github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/collection.rb

以下是代码:

MyModel.collection.group(
  :key      => :country_iso
  :initial  => { :object_id_set => {} },
  :reduce   => 'function (obj,prev) { prev.object_id_set[obj.object_id] = 1; }',
  :finalize => 'function (final)    { final.object_count = keys(final.object_id_set).length }'
)

答案 1 :(得分:0)

MyCollection.where(country_iso: "US").count

答案 2 :(得分:0)

一种不太聪明的方法就是滥用distinct ......

counts = MyModel.distinct(:country_iso).map do |country_iso|
  count = MyModel.where(:country_iso => country_iso).distinct(:object_id).count
  [country_iso, count]
end

......虽然这是每个国家的1个查询。每次查询可能不会是@ 1ms。