Ruby / Rails - Как агрегировать результаты запроса в массиве? - PullRequest
7 голосов
/ 12 февраля 2011

У меня большой набор данных, который я хочу очистить для пользователя.Набор данных из БД выглядит примерно так:

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, поэтому вместо этоговывод:

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

Любой совет, с чего начать?Это требование является новым для меня, поэтому я был бы признателен за ваши мысли о том, что вы думаете, что лучший способ решить эту проблему. Надеюсь, это может быть сделано в ruby, а не sql, так как поток активности, вероятно, будет расти в типах событий исложность.

Спасибо

Ответы [ 2 ]

10 голосов
/ 12 февраля 2011

Используйте group_by http://apidock.com/rails/Enumerable/group_by в Ruby или прямо в SQL. В рубине:

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

Тогда вы получите Hash вот так:

{ "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 для каждого_индекса

<% 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 голосов
/ 26 марта 2011

Я следую простому руководству по использованию group_by метода Enumerator.- Используемый набор данных должен быть небольшим, фиксированным и гарантированно оставаться постоянным во времени.

Например:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...