简体   繁体   中英

How do I count the number of records in a group using Active Record?

I have a list of files and a list of words that are in these files. The foreign_key is the field filenum . A file can have multiple occurances of a word, so wordtable can have a number of entries of filetable for one word with different word positions.

My Active Record classes are:

class File1 < ActiveRecord::Base
  self.table_name = :filetable
  self.primary_key = :FileNum
  belongs_to :word
end

class Word < ActiveRecord::Base
  self.table_name = :wordtable
  self.primary_key = :fileNum
  has_one :file1, foreign_key: :filenum, primary_key: :filenum
end

My query is:

query = 'ole'
Word.where(['name LIKE ?', "%#{query}%"]).group(:fileNum).each do |word, occurences|
  printf "%-24s %12s %12s\n" %  [word.name, word.file1.FilePath, occurences]
end

Here a subset of my current results:

ole       C:\Users\user\ruby\_nakijken\stringbuilder_list_properties.rb             
boolean   C:\Users\user\ruby\_nakijken\s_pinger.rb             
console   C:\Users\user\ruby\_nakijken\s_transition.rb
ole       C:\Users\user\ruby\_nakijken\save_outlook_message.rb   
...

The query works except for the total of occurences. I would like to have the number of occurences of that word in that file. How should I do that?

For the moment, id do it it a somewhat ugly way

query = 'require'
name, filenum, count, filepath = '', 0, 0, ''

Word.where(['name LIKE ?', "%#{query}%"]).group(:name, :filenum, :position).each do |word|
  if filenum == 0
    name, filenum, count, filepath = word.name, word.filenum, 1, word.file1.FilePath
  elsif name == word.name && filenum == word.filenum
    count += 1
  else
    printf "%-24s %12s (%s)\n" %  [name, filepath, count]
    name, filenum, count, filepath = word.name, word.filenum, 1, word.file1.FilePath
  end
end
if filenum == 0
  puts "'#{query}' not found"
else
  printf "%-24s %12s (%s)\n" %  [name, filepath, count]
end

Looking at the documentation :

If count is used with group , it returns a Hash whose keys represent the aggregated column, and the values are the respective amounts:

 Person.group(:city).count # => { 'Rome' => 5, 'Paris' => 3 } 

It seems you should add count to your query:

query = 'ole'
Word.where(['name LIKE ?', "%#{query}%"]).group(:fileNum).count.each do |fileNum, occurences|
  # ...
end

For your current solution (as my solution did not seem to work), I can suggest a little cleaner version, using group_by :

grouped_words = Word.where(['name LIKE ?', "%#{query}%"]).group(:name, :filenum, :position)
grouped_words.group_by { |group| [group.name, group.filenum] }.each do |(name, _), words|
  printf "%-24s %12s (%s)\n" %  [name, words.first.file1.FilePath, words.count]
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM