Created
March 7, 2022 10:53
-
-
Save abelards/3f07392ed583dbd03fce6ecb0cd935ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ENGLISH ABOVE, FRENCH BELOW -- VERSION FRANCAISE CI DESSOUS | |
# You want to tally something in Rails and you like Ruby so you've written | |
Object.pluck(:field).tally | |
# and the results look OK so you don't look further | |
{'ruby' => 999, 'python' => 300, 'java' => 42, 'C' => 1} | |
# But you're actually asking the database to do only SELECT objects.field, fetch 1342 records, and counting in Ruby | |
# Databases are quite cool and fast, and you'd rather do | |
"SELECT objects.field, COUNT(objects.field) AS objects_count FROM objects GROUP BY objects.field" | |
# followed by some ordering if you'd like | |
"ORDER BY objects_count DESC" | |
# Of course, don't write SQL, just write Ruby and Arel! | |
Object.group(:field).calculate(:count, :all) | |
Object.group(:field).count | |
# But if you ever need to add this to a more complicated request, here's how you can do: | |
table = Object | |
key = table.arel_table[:field] | |
request = table.reorder('objects_count DESC').select(key, key.count.as('objects_count')).group(key) | |
request.map{|record| [record.field, record.objects_count]} | |
--- | |
# Vous avez envie de compter des Objet par le nombre d'occurrence de champ et vous aimez Ruby donc vous faites | |
Objet.pluck(:champ).tally | |
# et vous avez un résultat OK : | |
{'ruby' => 999, 'python' => 300, 'java' => 42, 'C' => 1} | |
# Sauf que ça fait SELECT objets.champ en SQL, renvoie 1342 records et fait du comptage en Ruby. | |
# Et les bases de données sont très fortes pour ça, laissons-leur le travail avec | |
"SELECT objets.champ, COUNT(objets.champ) AS count FROM objets GROUP BY objets.champ" | |
# et peut-être même | |
"ORDER BY count DESC" | |
# Et arel vous permet de faire ça très bien : | |
Objet.group(:champ).calculate(:count, :all) | |
Objet.group(:champ).count | |
# mais si vous deviez l'intégrer dans une requête bien plus complexe, voici ce que vous pouvez faire : | |
table = Objet | |
key = table.arel_table[:champ] | |
request = table.reorder('objects_count DESC').select(key, key.count.as('objects_count')).group(key) | |
request.map{|record| [record.champ, record.objects_count]} | |
# Voilà, je pense que pas mal de gens ont ça (et souvent même sans tally mais avec des hash et des += 1) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment