Class: Trample::Search

Inherits:
Object
  • Object
show all
Includes:
Serializable
Defined in:
lib/trample/search.rb

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Serializable

#read_attribute_for_serialization

Class Attribute Details

._aggsObject

Returns the value of attribute _aggs.



13
14
15
# File 'lib/trample/search.rb', line 13

def _aggs
  @_aggs
end

._conditionsObject

Returns the value of attribute _conditions.



13
14
15
# File 'lib/trample/search.rb', line 13

def _conditions
  @_conditions
end

._modelsObject (readonly)

Returns the value of attribute _models.



14
15
16
# File 'lib/trample/search.rb', line 14

def _models
  @_models
end

Class Method Details

.aggregation(name, attrs = {}) {|| ... } ⇒ Object

Yields:

  • ()


30
31
32
33
34
35
# File 'lib/trample/search.rb', line 30

def self.aggregation(name, attrs = {})
  attrs.merge!(name: name)
  attrs[:order] = @_aggs.keys.length
  @_aggs[name] = Aggregation.new(attrs)
  yield @_aggs[name] if block_given?
end

.condition(name, attrs = {}) ⇒ Object



25
26
27
28
# File 'lib/trample/search.rb', line 25

def self.condition(name, attrs = {})
  attrs.merge!(name: name)
  @_conditions[name] = Condition.new(attrs)
end

.inherited(klass) ⇒ Object



19
20
21
22
23
# File 'lib/trample/search.rb', line 19

def self.inherited(klass)
  super
  klass._conditions = self._conditions.dup
  klass._aggs = self._aggs.dup
end

.model(*klasses) ⇒ Object



37
38
39
# File 'lib/trample/search.rb', line 37

def self.model(*klasses)
  @_models = klasses
end

.paginate(page_params) ⇒ Object



41
42
43
44
# File 'lib/trample/search.rb', line 41

def self.paginate(page_params)
  instance = new
  instance.paginate(page_params)
end

Instance Method Details

#agg(*names_or_payloads) ⇒ Object

todo refactor…



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/trample/search.rb', line 77

def agg(*names_or_payloads)
  names_or_payloads.each do |name_or_payload|
    name = name_or_payload
    selections = []
    if name_or_payload.is_a?(Hash)
      name = name_or_payload.keys.first if name_or_payload.is_a?(Hash)
      selections = Array(name_or_payload.values.first)
    end
    template = self.class._aggs[name.to_sym]
    raise AggregationNotDefinedError.new(self, name) unless template
    agg = self.aggregations.find { |a| a.name.to_sym == name.to_sym }

    if agg.nil?
      # N.B. deep dup so buckets don't mutate
      agg = Aggregation.new(deep_dup(template.attributes).merge(name: name.to_sym))
      agg.bucket_sort = template.bucket_sort
      self.aggregations << agg
    end

    selections.each do |key|
      bucket = agg.find_or_initialize_bucket(key)
      bucket.selected = true
    end
  end

  self
end

#aggregationsObject



120
121
122
123
# File 'lib/trample/search.rb', line 120

def aggregations
  @aggregations.sort! { |a, b| a.order <=> b.order }
  @aggregations
end

#aggregations=(aggregation_array) ⇒ Object

N.B rails may send nil here instead of empty array



106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/trample/search.rb', line 106

def aggregations=(aggregation_array)
  aggregation_array ||= []
  super([])

  aggregation_array.each do |aggregation_hash|
    if aggregation_hash[:buckets] # rails converting [] to nil
      selections = aggregation_hash[:buckets].select { |b| !!b[:selected] }.map { |b| b[:key] }
      agg(aggregation_hash[:name].to_sym => selections)
    else
      agg(aggregation_hash[:name].to_sym => [])
    end
  end
end

#backendObject



132
133
134
# File 'lib/trample/search.rb', line 132

def backend
  @backend ||= Backend::Searchkick.new(, self.class._models)
end

#condition(name) ⇒ Object



68
69
70
# File 'lib/trample/search.rb', line 68

def condition(name)
  ConditionProxy.new(name, self)
end

#conditions=(hash) ⇒ Object



125
126
127
128
129
130
# File 'lib/trample/search.rb', line 125

def conditions=(hash)
  super({})
  hash.each_pair do |name, value|
    condition(name).set(value)
  end
end

#includes(includes) ⇒ Object



72
73
74
# File 'lib/trample/search.rb', line 72

def includes(includes)
  self..records[:includes] = includes
end

#paginate(page_params) ⇒ Object



46
47
48
49
50
51
# File 'lib/trample/search.rb', line 46

def paginate(page_params)
  page_params ||= {}
  .pagination.current_page = page_params[:number] if page_params[:number]
  .pagination.per_page = page_params[:size] if page_params[:size]
  self
end

#query!Object



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/trample/search.rb', line 136

def query!
  @records = nil
  hash = backend.query!(conditions, aggregations)
  self..took = hash[:took]
  self..pagination.total = hash[:total]
  self.results = hash[:results]
  if !!.records[:load]
    records!
  else
    self.results
  end
end

#recordsObject

Todo only works for single-model search atm N.B. preserves sorting



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/trample/search.rb', line 151

def records
  @records ||= begin
                 queried = self.class._models.first.where(id: results.map(&:_id))
                 queried = queried.includes(.records[:includes])
                 [].tap do |sorted|
                   results.each do |result|
                     model = queried.find { |m| m.id.to_s == result.id.to_s }
                     sorted << model
                   end
                 end
               end
end

#records!Object



164
165
166
167
# File 'lib/trample/search.rb', line 164

def records!
  @records = nil
  records
end

#sort(*fields) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/trample/search.rb', line 53

def sort(*fields)
  return self if fields.empty?

  sorts = fields.map do |f|
    if f.to_s.starts_with?('-')
      f.sub!('-','')
      {att: f, dir: :desc}
    else
      {att: f, dir: :asc}
    end
  end
  self..sort = sorts
  self
end