2011-02-23 25 views
6

MoinMoin arasındaki fark,Raylar 3: Relation.count ve Relation.all.count

i ActiveRecord bir tutarsızlık tökezledi.
Büyük bir tablonun iki sütununda kullanılan tüm değer kombinasyonlarını elde etmeye çalıştım. İlk fikir:

SELECT DISTINCT col1, col2 FROM table 

bir model olarak yemek organize eden bir raylar app ve her Öğün has_many :noodles Her Erişte düşünün (ve dolayısıyla DB tablo sütunları) özelliklerini color ve shape sahiptir. Amacım, tek bir yemek için mevcut tüm kombinasyonların sayısını color ve shape almaktır. AR "farklı" bir yöntem sağlamaz yana

i

my_meal.noodles.select("distinct color, shape") 

kullanılabilir (raylar konsol stdout'ta olarak) 8 Erişte nesneleri (sırasıyla dize temsilcileri) bir altı satır çıkış var. Ama: Aslında my_meal yılında

>> my_meal.noodles.select("distinct color, shape").count 
=> 1606 

1606 erişte içerir. İlişkisini bir diziye dönüştürüp boyutlarını alırsam veya .all.count kullanırsam, sonuç doğrudur.

Bu nedenle sorum, AR neden 8 Nesne çıktı, ancak tüm DB satırlarını sayıyor?

Benzer bir sorun seems to be mentioned here fakat yanıt verilmiyor. bana doğru yönde itmek için tadman için

Teşekkür ve saygılarımla, Tim

+0

SQL oluşturuluyor araştırıp buradan gönderebilir miyim? Bu 'log/development.log' içinde saklanır ve genellikle çok açığa çıkar. – tadman

+0

Daha derinlere bakmak için: to_sql': my_meal.noodles.select ("farklı renk, şekil"). Count.to_sql'. – fl00r

+0

Aslında aynı testi denedim ve durumumda her şey yolunda gidiyor. Kont işini mükemmelleştirdi – fl00r

cevap

12

Tamam, teşekkürler.

Biraz daha derin kazdım (özellikle günlük dosyalarında) ve bulduğum şey biraz garip.

Soruna, seçilen sütunların sayısı neden oldu. biri yalnızca bir sütun seçer ve

my_meal.noodles.select("distinct color").count 

ActiveRecord aşağıdaki SQL deyimi oluşturur bir sonuç sayarsa: durumda bir

SELECT COUNT(distinct color) AS count_id FROM "NOODLES" WHERE ("NOODLES".meal_id = 295) 

iki veya daha fazla sütun seçer ve

my_meal.noodles.select("distinct color, shape").count 
için count geçerlidir

ActiveRecord, select maddesini unutur ve oluşturur:

SELECT COUNT(*) AS count_id FROM "NOODLES" WHERE ("NOODLES".meal_id = 295) 

(SQL) COUNT, parametre olarak yalnızca bir veya daha az sütuna izin verdiğinden, bu doğru olabilir. count önce group ekleyin ve bir şey gayet: Bunun dışında AS color_shape den

my_meal.noodles.select("distinct color, shape").group("color, shape").count 

SELECT COUNT(*) AS count_all, color, shape AS color_shape FROM "NOODLES" WHERE ("NOODLES".meal_id = 295) GROUP BY color, shape 

o beklediğim tam olduğunu. FAKAT...Sadece bu verir:

Garip bir dönüş değeri

my_meal.noodles.group("shape").count 

Sonuç sonucu ve geri dönüş değeri ile aynıdır (DB bağlıdır için ayrı) bir

>> my_meal.noodles.select("distinct color, shape").group("color, shape").count 
=> {star=>309, circle=>111, spaghetti=>189, square=>194, triangle=>179, bowtie=>301, shell=>93, letter=>230} 

>> my_meal.noodles.select("distinct color, shape").group("color, shape").count.class 
=> ActiveSupport::OrderedHash 

: vardır
pointed out here olarak İlişkiler arasındaki fark (matematiksel veya arel ilişkileri olabilir) ve ActiveRecord :: İlişkiler.
Bir modelin modeline mümkün olduğunca sık basmanın (en azından Rails uygulaması bağlamında) avantajlarını görebiliyorum.
Ancak, gerçek ilişkiler, bu işlemlerin bileşimi kombinasyonunun sonucu değil, bu işlemlerin birleşiminin sonucudur. Genel olarak ActiveRecord :: Relations zincirinin zincirlenebilirliği harika bir şeydir ancak takip edemediğim bazı tasarım kararları vardır.
Her bir eylemin, birlikte çalışmak için yeni bir ilişki döndürdüğüne dair güvenceye güvenemiyorsanız, bu, onun cazip çekiciliğinin çoğunu kaybeder.

zaman problemin çözümü için de, yukarıda sözü edilen group solüsyonu ve sayım işlemi için kirli bir çözüm bir tür kullanır:

my_meal.noodles.select("distinct color, shape").group("color, shape").all.count 

Bu çekerek önce kabul edilebilir bir minimuma sonuçları sıkıştırır Veritabanından çıkıp sadece saymak için pahalı nesneler yaratmak. Alternatif olarak, el yazısıyla yazılmış bir SQL sorgusu kullanılabilir, ancak neden bir Rails var ve kullanmıyorsunuz, ha? ;-) Yardımlarınız için

sayesinde
Tim