Class: Cloudsearchable::QueryChain

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/cloudsearchable/query_chain.rb

Overview

An object that represents a query to cloud search

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(domain, options = {}) ⇒ QueryChain

options:

- fatal_warnings: if true, raises a WarningInQueryResult exception on warning. Defaults to false


15
16
17
18
19
20
21
22
23
24
25
# File 'lib/cloudsearchable/query_chain.rb', line 15

def initialize(domain, options = {})
  @fatal_warnings = options.fetch(:fatal_warnings, false)
  @domain         = domain
  @q              = nil
  @clauses        = []
  @rank           = nil
  @limit          = 100000 # 10 is the CloudSearch default, 2kb limit will probably hit before this will
  @offset         = nil
  @fields         = Set.new
  @results        = nil
end

Instance Attribute Details

#domainObject (readonly)

Returns the value of attribute domain.



11
12
13
# File 'lib/cloudsearchable/query_chain.rb', line 11

def domain
  @domain
end

#fieldsObject (readonly)

Returns the value of attribute fields.



11
12
13
# File 'lib/cloudsearchable/query_chain.rb', line 11

def fields
  @fields
end

Instance Method Details

#each(&block) ⇒ Object



179
180
181
182
183
184
185
186
# File 'lib/cloudsearchable/query_chain.rb', line 179

def each(&block)
  materialize!
 if @results['hits']
   @results['hits']['hit'].each(&block)
 else
   raise "improperly formed response. hits parameter not available. messages: #{@results["messages"]}"
 end
end

#found_countObject



170
171
172
173
174
175
176
177
# File 'lib/cloudsearchable/query_chain.rb', line 170

def found_count
  materialize!
  if @results['hits']
    @results['hits']['found']
  else
    raise "improperly formed response. hits parameter not available. messages: #{@results["messages"]}"
  end
end

#limit(count) ⇒ Object

Limit the number of results returned from query to the given count.

Collection.search.limit(25)


102
103
104
105
106
107
# File 'lib/cloudsearchable/query_chain.rb', line 102

def limit count
  raise if materialized?
  raise "limit value must be must respond to to_i, #{count.class} does not" unless count.respond_to? :to_i
  @limit = count.to_i
  self
end

#materialize!Object

Executes the query, getting a result set, returns true if work was done, false if the query was already materialized. Raises exception if there was a warning and not in production.



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/cloudsearchable/query_chain.rb', line 153

def materialize!
  return false if materialized?
  
  @results = domain.execute_query(to_q)

  if @results && @results["info"] && messages = @results["info"]["messages"]
    messages.each do |message|
      if message["severity"] == "warning"
        Cloudsearchable.logger.warn "Cloud Search Warning: #{message["code"]}: #{message["message"]}"
        raise(WarningInQueryResult, "#{message["code"]}: #{message["message"]}") if @fatal_warnings
      end
    end
  end

  true
end

#materialized?Boolean

True if the query has been materialized (e.g. the search has been executed).

Returns:

  • (Boolean)


144
145
146
# File 'lib/cloudsearchable/query_chain.rb', line 144

def materialized?
  !@results.nil?
end

#offset(count) ⇒ Object

Offset the results returned by the query by the given count.

Collection.search.offset(250)


114
115
116
117
118
119
# File 'lib/cloudsearchable/query_chain.rb', line 114

def offset count
  raise if materialized?
  raise "limit value must be must respond to to_i, #{count.class} does not" unless count.respond_to? :to_i
  @offset = count.to_i
  self
end

#order(rank_expression) ⇒ Object

Set a rank expression on the query, overwriting any existing expression. Defaults to “-text_relevance”

Collection.search.order('created_at')  # order by the created_at field ascending
Collection.search.order('-created_at') # descending order

For more examples see docs.amazonwebservices.com/cloudsearch/latest/developerguide/tuneranking.html



90
91
92
93
94
95
# File 'lib/cloudsearchable/query_chain.rb', line 90

def order rank_expression
  raise if materialized?
  raise "order clause must be a string, not a #{rank_expression.class}" unless rank_expression.is_a? String
  @rank = rank_expression.to_s
  self
end

#returning(*fields) ⇒ Object

Adds a one or more fields to the returned result set, e.g.:

my_query.returning(:collection_id)
my_query.returning(:collection_id, :created_at)

x = [:collection_id, :created_at]
my_query.returning(x)


130
131
132
133
134
135
136
137
138
# File 'lib/cloudsearchable/query_chain.rb', line 130

def returning(*fields)
  raise if materialized?

  fields.flatten!
  fields.each do |f|
    @fields << f
  end
  self
end

#text(text) ⇒ Object

Allows searching by text, overwriting any existing text search.

Collection.search.text('mens shoes')

For more examples see docs.aws.amazon.com/cloudsearch/latest/developerguide/searching.text.html



76
77
78
79
80
# File 'lib/cloudsearchable/query_chain.rb', line 76

def text(text)
  raise if materialized?
  @q = text
  self
end

#to_qObject

Turns this Query object into a query string hash that goes on the CloudSearch URL

Raises:



191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/cloudsearchable/query_chain.rb', line 191

def to_q
  raise NoClausesError, "no search terms were specified" if (@clauses.nil? || @clauses.empty?) && (@q.nil? || @q.empty?)
  
  bq = (@clauses.count > 1) ? "(and #{@clauses.join(' ')})" : @clauses.first
  {
    q: @q,
    bq: bq,
    rank: @rank,
    size: @limit,
    start: @offset,
    :'return-fields' => @fields.reduce("") { |s,f| s << f.to_s }
  }
end

#where(field_or_hash, op = nil, value = nil) ⇒ Object

This method can be called in several different forms.

To do an equality search on several fields, you can pass a single hash, e.g.:

Collection.search.where(customer_id: "12345", another_field: "Some value")

To do a search on a single field, you can pass three parameters in the form: where(field, op, value)

Collection.search.where(:customer_id, :==, 12345)

The value you provide must be of the same type as the field. For text and literal values, provide a string value. For uint fields, provide a numeric value.

To search for any of several possible values for a field, use the :any operator:

Collection.search.where(:product_group, :any, %w{gl_kitchen gl_grocery})

Equality and inequality operators (:==, :!=, :<, :<=, :>, :>=) are supported on integers, and equality operators are supported on all scalars. Currently, special operators against arrays (any and all) are not yet implemented.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/cloudsearchable/query_chain.rb', line 50

def where(field_or_hash, op = nil, value = nil)
  raise if materialized?

  if field_or_hash.is_a? Hash
    field_or_hash.each_pair do |k, v| 
      where(k, :==, v)
    end
  elsif field_or_hash.is_a? Symbol
    if (field = domain.fields[field_or_hash.to_sym]).nil?
      raise "cannot query on field '#{field_or_hash}' because it is not a member of this index"
    end
    @clauses << clause_for(field_or_hash, field.type, op, value)
  else
    raise "field_or_hash must be a Hash or Symbol, not a #{field_or_hash.class}"
  end

  self
end