pg_search icon indicating copy to clipboard operation
pg_search copied to clipboard

Minimum character for prefix true option

Open princejoseph opened this issue 5 years ago • 2 comments

Is there a way I can specify minimum number of characters for prefix? Right now, it returns even for the first character.

class Toon < ActiveRecord::Base
  include PgSearch

  pg_search_scope :search_by_name, 
                  against: :name, 
                  tsearch: { 
                    prefix: true
                  }
end
cowboy_bebop = Toon.create!(name: 'cowboy bebop')

Toon.search_by_name 'cow' # => [cowboy_bebop]
Toon.search_by_name 'co' # => [cowboy_bebop]
Toon.search_by_name 'c' # => [cowboy_bebop]

I was thinking of something like this (see min_prefix key):

class Toon < ActiveRecord::Base
  include PgSearch

  pg_search_scope :search_by_name, 
                  against: :name, 
                  tsearch: { 
                    prefix: true, 
                    min_prefix: 3 
                  }
end

which will act like this:

Toon.search_by_name 'cow' # => [cowboy_bebop]
Toon.search_by_name 'co' # => []
Toon.search_by_name 'c' # => []

princejoseph avatar Jun 20 '19 21:06 princejoseph

I have the same problem.

first = Good.create!(title: 'iPhone 5 Battery')
second = Good.create!(title: 'iPhone 5s Battery') 
pg_search_scope :search_by_all, associated_against: {
      models: [:title],
      brands: [:title],
      part: [:title]
  }, using: {
      tsearch: { prefix: true }
  }
Good.search_by_all 'iphone 5 batt'

It's return first and second goods if prefix true. But If it were possible to set min length prefix, then the correct result would be returned

It may be possible to manually specify the tag if you need to find it using the prefix ? I used this practice when splitting a string into an array.

array = [...]
array.each do |a|
 if a.length > 3
   a = a + '*'
 end
end

Result: 'iphone 5 batt*'

Vlagilen avatar Feb 27 '20 01:02 Vlagilen

I'v solved this problem, it's not quite beautiful, but it works. If you run the search twice, the first time with the (prefix: true) parameter, the second time (you can also configure associations for yourself) without it.

params[:search] = 'iPhone 5 battery'

pg_search_scope :search_all, against: [:title, :tag, :barcode], associated_against: {
      models: [:title],
      brands: [:title]
  }, using: {
      tsearch: {prefix: true}
  }
pg_search_scope :search_model, associated_against: {
      models: [:title]
}

The next step in the controller is to search for the length of the word we need in the string that will fit our condition. (greater than 3 or as in my case equal to 1)

model = nil
a = params[:search].split(' ') # transform our string into an array ['iPhone', '5', 'battery']
a.each do |item|
   item.length == 1 ? model = item : nil # search our model (or length > 3 as you want)
end
search = Part.search_all(params[:search]) # First search method
!model.blank? ? search = search.search_model(model) : nil # If we find a model, we do a second search without the parameter (prefix: true)

return search

Vlagilen avatar Feb 28 '20 02:02 Vlagilen