2009-05-24 20 views
29

Wykonuję obliczenia statyki w moim produkcie. Użytkownik wykonał szereg operacji, powiedzmy komentarze opublikowane. Chcę móc pokazać im, ile tygodni tygodniowo lub tygodniowo zamieszczali komentarze w ciągu ostatniego tygodnia.Grupowanie według tygodnia/miesiąca/etc i ActiveRecord?

Czy jest jakiś sposób na zbieranie danych w ten sposób za pomocą activerecord? Czy najlepiej zrobić to ręcznie - aby powtórzyć podsumowywanie rekordów na podstawie własnych kryteriów?

class User < ActiveRecord::Base 
    has_many :comments 
end 

class Comments < ActiveRecord::Base 
    belongs_to :user 
end 

@user.comments(:all).map {|c| ...do my calculations here...} 

czy jest jakiś lepszy sposób?

dziękuję! Oren

Odpowiedz

26

W tym przypadku najlepszym rozwiązaniem dla mnie było albo wcale go w prostej SQL, lub korzystać z funkcji activerecord group_by:

@user.all.group_by{ |u| u.created_at.beginning_of_month } 
+10

'group_by' nie jest metodą ActiveRecord, ale raczej metodą Ruby na" Enumerable ". – Laurens

+0

Samo użycie 'u.created_at.month' jest krótsze –

+11

Nie należy ładować wszystkich rekordów z bazy danych, tworzyć obiektów ActiveRecord, analizować dat w obiekty świadome strefy czasowej ActiveSupport - wszystko po to, aby obliczyć liczbę rekordów. –

13

Moje przypuszczenie byłoby coś jak:

@user.comments.count(:group => "year(created_at),month(created_at)") 

Dry-code, YMMV

+0

Wierzę, że będzie to również grupować się w kolejnych miesiącach, więc jeśli masz dwa lata danych, wszystkie rzeczy w styczniu 1 i roku 2. To, czego szukam, to sposób na 24 okno miesiąca, na przykład ile miesięcy. – teich

+0

Możesz dodać warunek ograniczenia roku także, np .: conditions => [: created_at, "> # {24.months.ago}"]. Ponownie nietestowane, ale powinno być możliwe z czymś takim. –

+0

Wydaje się, że jest to mysql specific – Tachyons

2

Zapoznaj się z wtyczki has_activity.

+0

Dzięki za wskaźnik. Wygląda na to, że has_activity jest tylko mysql. Mój host produkcji to postgresql. – teich

66

W PostgreSQL można zrobić:

@user.comments.group("DATE_TRUNC('month', created_at)").count 

dostać:

{"2012-08-01 00:00:00"=>152, "2012-07-01 00:00:00"=>57, "2012-09-01 00:00:00"=>132} 

przyjmuje wartości z „mikrosekund” na „tysiąclecia” do grupowania: http://www.postgresql.org/docs/8.1/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC

+4

O wiele szybciej niż przy użyciu przelicznika ruby ​​group_by! –

+0

Wojtek, a co powiesz o tym, kiedy nic nie powstało w ciągu miesiąca? Nic nie dostajesz za ten miesiąc. –

+1

@MattSmith Wierzę, że tak. Na szczęście łatwo jest podać wartość domyślną podczas odczytu wartości z wyników tego zapytania: '' 'output.fetch (" 2012-08-01 00:00:00 ", 0)' '' –

16

Oto bardziej wyrafinowana wersja tej

@user.comments.group("year(created_at)").group("month(created_at)").count 
4

Korzystanie group_by

@user.comments.group_by(&:week) 

class User < ActiveRecord::Base 
    def week 
    some_attribute_like_date.strftime('%Y-%W') 
    end 
end 

To daje zgrupowane listy w formacie YYYY-WW

2

wyjazdu Data grupy klejnot

https://github.com/ankane/groupdate

ma ostatnie zatwierdzenia, działa z postgresql, łatwo integruje się z kopią wykresu do szybkiego tworzenia wykresów i działa ze strefami czasowymi !!

+0

GroupDate działa tylko z UTC, więc jeśli używasz innej strefy czasowej w swojej bazie danych, rozważ alternatywę. – msdundar

Powiązane problemy