Class: Ripple::Criteria

Inherits:
Object
  • Object
show all
Includes:
Enumerable, Translation
Defined in:
lib/ripple_searchable/criteria.rb

Overview

chainable Criteria methods such as :where, :lt, :lte, :gt, :gte, :between, with sort, :skip, :limit options

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass) ⇒ Criteria

Returns a new instance of Criteria.



16
17
18
19
# File 'lib/ripple_searchable/criteria.rb', line 16

def initialize(klass)
  @selector, @klass, @options, @documents, @cached = "", klass, {}
  clear_cache
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



305
306
307
308
309
310
311
312
313
# File 'lib/ripple_searchable/criteria.rb', line 305

def method_missing(name, *args, &block)
  if klass.respond_to?(name)
    klass.send(:with_scope, self) do
      klass.send(name, *args, &block)
    end
  else
    super
  end
end

Instance Attribute Details

#cachedObject

Returns the value of attribute cached.



14
15
16
# File 'lib/ripple_searchable/criteria.rb', line 14

def cached
  @cached
end

#docsObject

Returns the value of attribute docs.



14
15
16
# File 'lib/ripple_searchable/criteria.rb', line 14

def docs
  @docs
end

#document_idsObject

Array of matching document id’s



238
239
240
# File 'lib/ripple_searchable/criteria.rb', line 238

def document_ids
  @document_ids
end

#klassObject

Returns the value of attribute klass.



14
15
16
# File 'lib/ripple_searchable/criteria.rb', line 14

def klass
  @klass
end

#optionsObject

Returns the value of attribute options.



14
15
16
# File 'lib/ripple_searchable/criteria.rb', line 14

def options
  @options
end

#responseObject

Returns the value of attribute response.



14
15
16
# File 'lib/ripple_searchable/criteria.rb', line 14

def response
  @response
end

#selectorObject

Returns the value of attribute selector.



14
15
16
# File 'lib/ripple_searchable/criteria.rb', line 14

def selector
  @selector
end

#totalObject

Total number of matching documents



232
233
234
# File 'lib/ripple_searchable/criteria.rb', line 232

def total
  @total
end

Instance Method Details

#==(other) ⇒ Object



259
260
261
# File 'lib/ripple_searchable/criteria.rb', line 259

def ==(other)
  self.klass == other.klass && self.selector == other.selector && self.options == other.options
end

#between(*criterion) ⇒ Object

Add an Range selector. Values in the passed hash can be either a Range or an Array. of the passed hash has multiple elements, the condition will be AND. The range is inclusive.

Example

Product.between(availibility: 1..3, price: [12, 20])

will append this selector: “((availibility:[1 TO 3] AND price:[12 TO 20]))”



70
71
72
73
74
75
76
77
78
# File 'lib/ripple_searchable/criteria.rb', line 70

def between(*criterion)
  clone.tap do |crit|
    crit.add_restriction do
      criterion.each do |c|
        crit.add_restriction(to_lucene_pair(c, operator: "BETWEEN"))
      end
    end
  end
end

#count(extras = false) ⇒ Integer

Get the count of matching documents in the database for the context.

Examples:

Get the count without skip and limit taken into consideration.

context.count

Get the count with skip and limit applied.

context.count(true)

Parameters:

  • extras (Boolean) (defaults to: false)

    True to inclued previous skip/limit statements in the count; false to ignore them. Defaults to ‘false`.

Returns:

  • (Integer)

    The count of documents.



287
288
289
290
291
292
293
# File 'lib/ripple_searchable/criteria.rb', line 287

def count(extras = false)
  if extras
    self.total
  else
    super()
  end
end

#documentsObject

Returns the matched documents



217
218
219
220
221
222
223
224
225
# File 'lib/ripple_searchable/criteria.rb', line 217

def documents
  if @cached
    @documents
  else
    parse_response
    @cached = true
    @documents = self.klass.find self.document_ids
  end
end

#each(&block) ⇒ Object



227
228
229
# File 'lib/ripple_searchable/criteria.rb', line 227

def each(&block)
  documents.each(&block)
end

#executeObject

Executes the search query

Raises:



211
212
213
214
# File 'lib/ripple_searchable/criteria.rb', line 211

def execute
  raise CriteriaError, t('empty_selector_error') if self.selector.blank?
  @response = @klass.search self.selector, self.options
end

#gt(*criterion) ⇒ Object

Add a ‘greater than’ selector

Example

Product.gt(quantity: 0, ratings: 5)

will append this selector: “((quantity:TO * AND ratings:TO *))”



145
146
147
148
149
150
151
152
153
154
# File 'lib/ripple_searchable/criteria.rb', line 145

def gt(*criterion)
  clone.tap do |crit|
    crit.add_restriction do
      criterion.each do |c|
        c.each {|k,v| c[k]=Array.wrap(v).push("*")}
        crit.add_restriction(to_lucene_pair(c, operator: "BETWEEN", exclusive: true))
      end
    end
  end
end

#gte(*criterion) ⇒ Object

Add a ‘greater or equal than’ selector

Example

Product.gte(quantity: 0, ratings: 5)

will append this selector: “((quantity:[0 TO *] AND ratings:[5 TO *]))”



107
108
109
110
111
112
113
114
115
116
# File 'lib/ripple_searchable/criteria.rb', line 107

def gte(*criterion)
  clone.tap do |crit|
    crit.add_restriction do
      crit.criterion.each do |c|
        c.each {|k,v| c[k]=Array.wrap(v).push(10**20)}
        crit.add_restriction(to_lucene_pair(c, operator: "BETWEEN"))
      end
    end
  end
end

#in_batches(limit = 1000) ⇒ Object



295
296
297
298
299
300
301
302
303
# File 'lib/ripple_searchable/criteria.rb', line 295

def in_batches(limit=1000)
  skip = 0
  objects = self.limit(limit).skip(skip*limit)
  while objects.count(true) > 0
    yield objects
    skip+=1
    objects = self.limit(limit).skip(skip*limit)
  end
end

#initialize_copy(other) ⇒ Object



263
264
265
266
267
268
269
270
271
272
273
# File 'lib/ripple_searchable/criteria.rb', line 263

def initialize_copy(other)
  @selector = other.selector.dup
  @options = other.options.dup
  if other.response.present?
    @response = other.response.dup
    @documents = other.documents.dup
    @docs = other.docs.dup
    @document_ids = other.document_ids.dup
  end
  super
end

#limit(limit) ⇒ Object Also known as: rows

Add limit option to criteria. Useful for pagination. Default is 10.

Example

Product.between(availibility:[1,3]).limit(10)

will limit the number of returned documetns to 10



185
186
187
188
189
190
# File 'lib/ripple_searchable/criteria.rb', line 185

def limit(limit)
  clone.tap do |crit|
    crit.clear_cache
    crit.options[:rows] = limit
  end
end

#lt(*criterion) ⇒ Object

Add a ‘less than’ selector

Example

Product.lt(quantity: 10, ratings: 5)

will append this selector: “((quantity:TO 10 AND ratings:TO 5))”



126
127
128
129
130
131
132
133
134
135
# File 'lib/ripple_searchable/criteria.rb', line 126

def lt(*criterion)
  clone.tap do |crit|
    crit.add_restriction do
      criterion.each do |c|
        c.each {|k,v| c[k]=Array.wrap(v).unshift("*")}
        crit.add_restriction(to_lucene_pair(c, operator: "BETWEEN", exclusive: true))
      end
    end
  end
end

#lte(*criterion) ⇒ Object

Add a ‘less or equal than’ selector

Example

Product.lte(quantity: 10, ratings: 5)

will append this selector: “((quantity:[* TO 10] AND ratings:[* TO 5]))”



88
89
90
91
92
93
94
95
96
97
# File 'lib/ripple_searchable/criteria.rb', line 88

def lte(*criterion)
  clone.tap do |crit|
    crit.add_restriction do
      crit.criterion.each do |c|
        c.each {|k,v| c[k]=Array.wrap(v).unshift(10**20)}
        crit.add_restriction(to_lucene_pair(c, operator: "BETWEEN"))
      end
    end
  end
end

#merge(criteria) ⇒ Object



243
244
245
246
247
# File 'lib/ripple_searchable/criteria.rb', line 243

def merge(criteria)
  crit = clone
  crit.merge!(criteria)
  crit
end

#merge!(criteria) ⇒ Object



249
250
251
252
253
# File 'lib/ripple_searchable/criteria.rb', line 249

def merge!(criteria)
  add_restriction criteria.selector
  self.options.merge!(criteria.options)
  self
end

#or(*criterion) ⇒ Object Also known as: any_of

Add an OR selector

Example

Product.or({name: "Pants"}, {name: "Shirt"})

will append this selector: “((name:Pants) OR (name:Shirt))”



48
49
50
51
52
53
54
55
56
# File 'lib/ripple_searchable/criteria.rb', line 48

def or(*criterion)
  clone.tap do |crit|
    crit.add_restriction do
      criterion.each do |c|
        crit.add_restriction(to_lucene_pair(c, operator: "OR"), operator: "OR" )
      end
    end
  end
end

#skip(skip) ⇒ Object Also known as: start

Add skip option to criteria. Useful for pagination. Default is 0.

Example

Product.between(availibility:[1,3]).skip(10)


200
201
202
203
204
205
# File 'lib/ripple_searchable/criteria.rb', line 200

def skip(skip)
  clone.tap do |crit|
    crit.clear_cache
    crit.options[:start] = skip
  end
end

#sort(sort_options) ⇒ Object Also known as: order_by, order

Add sort options to criteria

Example

Product.between(availibility:[1,3]).sort(availibility: :asc, created_at: :desc)

will append this sort option: “availibility asc, created_at desc”



164
165
166
167
168
169
170
171
172
173
# File 'lib/ripple_searchable/criteria.rb', line 164

def sort(sort_options)
  clone.tap do |crit|
    case sort_options
    when String
      crit.add_sort_option sort_options
    when Hash
      sort_options.each {|k,v| crit.add_sort_option "#{k} #{v.downcase}"}
    end
  end
end

#to_procObject



255
256
257
# File 'lib/ripple_searchable/criteria.rb', line 255

def to_proc
  ->{ self }
end

#where(selector = nil) ⇒ Object

Main criteria selector to search records

Example

Model.where(tags: "nerd", name: "Joe", something: 2)

will append this selector: “(tags:nerd AND name:Joe AND something:2)”



29
30
31
32
33
34
35
36
37
38
# File 'lib/ripple_searchable/criteria.rb', line 29

def where(selector = nil)
  clone.tap do |crit|
    case selector
    when String
      crit.add_restriction selector
    when Hash
      crit.add_restriction to_lucene_pair(selector)
    end
  end
end