Module: Polysearch::Searchable

Extended by:
ActiveSupport::Concern
Defined in:
app/models/polysearch/searchable.rb

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#similarity_ngramsObject



118
119
120
121
122
# File 'app/models/polysearch/searchable.rb', line 118

def similarity_ngrams
  similarity_words.each_with_object(Set.new) do |word, memo|
    ngrams(word).each { |ngram| memo << ngram }
  end.to_a.sort_by(&:length)
end

#similarity_wordsObject



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'app/models/polysearch/searchable.rb', line 104

def similarity_words
  tsvectors = to_tsvectors.compact.uniq
  return [] if tsvectors.blank?
  tsvector = tsvectors.join(" || ")

  ts_stat = Arel::Nodes::NamedFunction.new("ts_stat", [
    Arel::Nodes::SqlLiteral.new(sanitize_sql_value("SELECT #{tsvector}"))
  ])
  length = Arel::Nodes::NamedFunction.new("length", [Arel::Nodes::SqlLiteral.new(quote_column_name(:word))])
  query = self.class.unscoped.select(:word).from(ts_stat.to_sql).where(length.gteq(3)).to_sql
  result = self.class.connection.execute(query)
  result.values.flatten
end

#similarity_words_tsvectors(weight: "D") ⇒ Object



124
125
126
127
128
# File 'app/models/polysearch/searchable.rb', line 124

def similarity_words_tsvectors(weight: "D")
  similarity_ngrams.each_with_object([]) do |ngram, memo|
    memo << make_tsvector(ngram, weight: weight)
  end
end

#to_tsvectorsObject

Polysearch::Searchable#to_tsvectors is abstract… a noop by default it must be implemented in including ActiveRecord models if this behavior is desired

Example:

def to_tsvectors

[]
  .then { |result| result << make_tsvector(EXAMPLE_COLUMN_OR_PROPERTY, weight: "A") }
  .then { |result| EXAMPLE_TAGS_COLUMN.each_with_object(result) { |tag, memo| memo << make_tsvector(tag, weight: "B") } }

end



100
101
102
# File 'app/models/polysearch/searchable.rb', line 100

def to_tsvectors
  []
end

#update_polysearchObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'app/models/polysearch/searchable.rb', line 62

def update_polysearch
  return unless persisted?
  tsvectors = to_tsvectors.compact.uniq
  return if tsvectors.blank?

  tsvectors.pop while tsvectors.size > 500
  tsvectors.concat similarity_words_tsvectors
  tsvector = tsvectors.join(" || ")

  attributes = {
    searchable_type: self.class.name,
    searchable_id: id,
    words: similarity_words.join(" "),
    created_at: Time.current,
    updated_at: Time.current
  }

  result = Polysearch::Record.upsert(
    attributes,
    unique_by: [:searchable_type, :searchable_id],
    returning: :id
  )

  record = Polysearch::Record.find_by(id: result.first["id"])
  record.update_value tsvector
end