2011-02-11 94 views
7

我有一个大数据集,我想为用户清理。该数据从数据库设置看起来是这样的:Ruby/Rails - 如何聚合数组中的查询结果?

ID | project_id | thread_id | action_type |description 
1 | 10   | 30  | comment | yada yada yada yada yada 
1 | 10   | 30  | comment | xxx 
1 | 10   | 30  | comment | yada 313133 
1 | 10   | 33  | comment | fdsdfsdfsdfsdfs 
1 | 10   | 33  | comment | yada yada yada yada yada 
1 | 10   |   | attachment | fddgaasddsadasdsadsa 
1 | 10   |   | attachment | xcvcvxcvxcvxxcvcvxxcv 

现在,当我输出如上上述,我在同样的顺序查看它,问题是,它是很重复。例如,对于PROJECT_ID 10 & THREAD_ID 30你看:

10 - 30 - yada yada yada yada yada 
10 - 30 - xxxxx 
10 - 30 - yada yada yada yada yada 

我想什么来学习如何在Ruby中做的,是一些如何创建一个PROJECT_ID和thread_id,则下一个数组,aggreate描述,所以不是输出是:

10 - 30 
- yada yada yada yada yada 
- xxxxx 
- yada yada yada yada yada 

有关从哪里开始的建议?这个要求对我来说是新的,所以我会很感激你对你正在考虑解决问题的最好方法的想法。希望这可以通过ruby而不是sql来完成,因为活动提要可能会随着事件类型和复杂。

感谢

+0

对于SQL方法使用GROUP BY。对于Ruby方法,使用Enumerable#group_by。检查文档。 – tokland 2011-02-11 23:15:19

+1

这些数据采用何种形式?它是ActiveRecord对象还是JSON对象或其他东西? – 2011-02-11 23:16:25

回答

10

使用group_by​​在Ruby或右SQL。在Ruby:

sets = DataSet.all.group_by{ |data| [data.project_id, "-", data.thread_id].join(" ") } 

然后你会得到散列这样的:

{ "10 - 30" => [#DataSet1, #DataSet2 ...], "10 - 33" => [#DataSet7, #DataSet11 ...] 

您可以在视图解析:

<% sets.each do |range, datas| %> 
    <p><%= range %>:</p> 
    <% datas.each do |data| %> 
    <p><%= data.description %></p> 
    <% end %> 
<% end %> 

UPD为each_with_index

<% sets.each_with_index do |datas, index| %> 
    <p><%= datas[0] %>:</p> 
    <% datas[1].each do |data| %> 
    <p><%= data.description %></p> 
    # some stuff with *last* 
    <%= "This is the last one" if data == datas[1].last %> 
    <% end %> 
<% end %> 
0

我遵循使用Enumeratorgroup_by方法的简单指南。 - 正在操作的数据集应该很小并且是固定的,并且保证随时间保持恒定。

如:

Fixed data-set: Zip codes, city names  
Dynamic but small data-set: User's hobbies  
Dynamic but paginated data-set: First page of latest orders. 

在我看来您的活动资讯表可以随时间快速增长。 Activity.all将所有活动加载到内存中。执行此调用会导致内存和网络成本过高。在没有条件和分页的情况下执行all呼叫绝不是一个好主意。如果您当前正在对结果集进行分页,则当结果集跨越多个页面时,当前的解决方案将不起作用。您必须使用order子句才能获得正确的结果集。

这是我会做什么:

在你的控制器:

# order by ensures that ordering happens at the DB 
# pagination and conditions ensures that data set is small 
activities = Activity.paginate(:order => "project_id, thread_id", :page => #pn) 
@activity_groups = activities.group_by{|a| "#{a.project_id} - #{a.thread_id}"} 

现在,您可以在视图中使用@activity_groups通过fl00r的建议。