Bonjour,
Je bidouille un peu RoR en dilettante, essentiellement pour travailler sur des BDD persos avec une interface facile à mettre en place et pratique.
Jusque là, je m'étais toujours débrouillé seul en cas de problème, mais là, je sèche complètement.
Mon projet consiste en une BDD dont l'objectif est d'obtenir des stats sur les occurrences de mots dans des corpus de textes.
J'ai donc une table textes
Code Ruby : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 create_table "textes", force: :cascade do |t| t.string "titre" t.string "alpha" t.text "contenu" t.boolean "fait" t.integer "nb_mots", default: 0, null: false t.index ["alpha", "titre"], name: "index_textes_on_alpha_and_titre" end
une table lemmes (les lemmes sont les mots en tant qu'entrées dans le dictionnaire)
Code Ruby : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 create_table "lemmes", force: :cascade do |t| t.string "libelle" t.string "alpha" t.integer "category_id" t.integer "textes_compteur", default: 0, null: false t.index ["alpha", "libelle"], name: "index_lemmes_on_alpha_and_libelle" t.index ["category_id"], name: "index_lemmes_on_category_id" end
Une table compteurs pour les lier :
Code Ruby : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 create_table "compteurs", force: :cascade do |t| t.integer "texte_id" t.integer "lemme_id" t.integer "occurences", default: 0 t.index ["lemme_id"], name: "index_compteurs_on_lemme_id" t.index ["texte_id", "lemme_id"], name: "index_compteurs_on_texte_id_and_lemme_id", unique: true t.index ["texte_id"], name: "index_compteurs_on_texte_id" end
et une table categories qui sert aussi pour la requête :
Code Ruby : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 create_table "categories", force: :cascade do |t| t.string "libelle" end
Je voudrais lister, pour chaque lemme, son libelle, celui de la catégorie associée, le compte du nombre de texte dans lequel il figure, et la somme de toutes les occurences du mot dans lesdits textes, avec éventuellement une sous-requête pour les textes
En pur SQL, je peux faire ça sans soucis :
Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 SELECT lemmes.libelle AS mot, categories.libelle AS categorie, count(compteurs.occurences) AS nb_textes, sum(compteurs.occurences) AS tot_occurences FROM lemmes LEFT JOIN compteurs ON lemmes.id = compteurs.lemme_id INNER JOIN categories ON categories.id = lemmes.category_id WHERE compteurs.texte_id IN (1, 2) GROUP BY compteurs.lemme_id;
Mais sous rails, j'ai plus de mal à obtenir ce que je veux, combiner directement les méthodes select, group, joins, sum et count semble définitivement une mauvaise idée (surtout à cause de count et sum)
Pour l'instant, le mieux que j'aie pu obtenir c'est ceci (dans la classe/model Compteur) :
Ça fonctionne, mais ça ne me semble ni très élégant, ni dans l'esprit rails, En plus, ça va systématiquement exécuter 2N+1 requêtes. N étant le nombre de lemmes.
Code Ruby : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 def self.lemmes_stats(textes = nil) textes ||= Texte.select(:id) lemmes = Lemme.joins(:category).eager_load(:category) results = [] lemmes.each do |l| h = {} h[:lemme] = l.libelle h[:category] = l.category.libelle h[:count] = self.where(lemme_id: l.id, texte_id: textes).count(:occurences) h[:sum] = self.where(lemme_id: l.id, texte_id: textes).sum(:occurences) results.push(h) end return results end
Donc si quelqu'un pouvait me proposer un meilleur moyen d'obtenir une telle liste, je lui en serai reconnaissant. Sinon... ben tant pis, je me contenterait de questionner directment la BDD via DB Browser.
Merci d'avance !
Partager