Class: Aws::Record::BuildableSearch

Inherits:
Object
  • Object
show all
Defined in:
lib/aws-record/record/buildable_search.rb

Constant Summary collapse

SUPPORTED_OPERATIONS =
[:query, :scan]

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ BuildableSearch

This should never be called directly, rather it is called by the #build_query or #build_scan methods of your aws-record model class.



8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/aws-record/record/buildable_search.rb', line 8

def initialize(opts)
  operation = opts[:operation]
  model = opts[:model]
  if SUPPORTED_OPERATIONS.include?(operation)
    @operation = operation
  else
    raise ArgumentError.new("Unsupported operation: #{operation}")
  end
  @model = model
  @params = {}
  @next_name = "BUILDERA"
  @next_value = "buildera"
end

Instance Method Details

#complete!Aws::Record::ItemCollection

You must call this method at the end of any query or scan you build.

Returns:



229
230
231
# File 'lib/aws-record/record/buildable_search.rb', line 229

def complete!
  @model.send(@operation, @params)
end

#consistent_read(b) ⇒ Object

If true, will perform your query or scan as a consistent read. If false, the query or scan is eventually consistent.



32
33
34
35
# File 'lib/aws-record/record/buildable_search.rb', line 32

def consistent_read(b)
  @params[:consistent_read] = b
  self
end

#exclusive_start_key(key) ⇒ Object

If you have an exclusive start key for your query or scan, you can provide it with this builder method. You should not use this if you are querying or scanning without a set starting point, as the ItemCollection class handles pagination automatically for you.



69
70
71
72
# File 'lib/aws-record/record/buildable_search.rb', line 69

def exclusive_start_key(key)
  @params[:exclusive_start_key] = key
  self
end

#filter_expr(statement_str, *subs) ⇒ Object

Provide a filter expression for your query or scan using a substitution expression.

Examples:

Building a simple scan:

# Example model class
class ExampleTable
  include Aws::Record
  string_attr  :uuid, hash_key: true
  integer_attr :id,   range_key: true
  string_attr  :body
end

scan = ExampleTable.build_scan.filter_expr(
  "contains(:body, ?)",
  "bacon"
).complete!


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/aws-record/record/buildable_search.rb', line 127

def filter_expr(statement_str, *subs)
  names = @params[:expression_attribute_names]
  if names.nil?
    @params[:expression_attribute_names] = {}
    names = @params[:expression_attribute_names]
  end
  values = @params[:expression_attribute_values]
  if values.nil?
    @params[:expression_attribute_values] = {}
    values = @params[:expression_attribute_values]
  end
  prepared = _key_pass(statement_str, names)
  statement = _apply_values(prepared, subs, values)
  @params[:filter_expression] = statement
  self
end

#key_expr(statement_str, *subs) ⇒ Object

Provide a key condition expression for your query using a substitution expression.

Examples:

Building a simple query with a key expression:

# Example model class
class ExampleTable
  include Aws::Record
  string_attr  :uuid, hash_key: true
  integer_attr :id,   range_key: true
  string_attr  :body
end

q = ExampleTable.build_query.key_expr(
      ":uuid = ? AND :id > ?", "smpl-uuid", 100
    ).complete!
q.to_a # You can use this like any other query result in aws-record


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/aws-record/record/buildable_search.rb', line 90

def key_expr(statement_str, *subs)
  unless @operation == :query
    raise ArgumentError.new("key_expr is only supported for queries.")
  end
  names = @params[:expression_attribute_names]
  if names.nil?
    @params[:expression_attribute_names] = {}
    names = @params[:expression_attribute_names]
  end
  values = @params[:expression_attribute_values]
  if values.nil?
    @params[:expression_attribute_values] = {}
    values = @params[:expression_attribute_values]
  end
  prepared = _key_pass(statement_str, names)
  statement = _apply_values(prepared, subs, values)
  @params[:key_condition_expression] = statement
  self
end

#limit(size) ⇒ Object

Allows you to set a page size limit on each query or scan request.



176
177
178
179
# File 'lib/aws-record/record/buildable_search.rb', line 176

def limit(size)
  @params[:limit] = size
  self
end

#multi_model_filter(proc = nil, &block) ⇒ Object

Allows you to define a callback that will determine the model class to be used for each item, allowing queries to return an ItemCollection with mixed models. The provided block must return the model class based on any logic on the raw item attributes or `nil` if no model applies and the item should be skipped. Note: The block only has access to raw item data so attributes must be accessed using their names as defined in the table, not as the symbols defined in the model class(s).

Examples:

Scan with heterogeneous results:

# Example model classes
class Model_A
  include Aws::Record
  set_table_name(TABLE_NAME)

  string_attr :uuid, hash_key: true
  string_attr :class_name, range_key: true

  string_attr :attr_a
end

class Model_B
  include Aws::Record
  set_table_name(TABLE_NAME)

  string_attr :uuid, hash_key: true
  string_attr :class_name, range_key: true

  string_attr :attr_b
end

# use multi_model_filter to create a query on TABLE_NAME
items = Model_A.build_scan.multi_model_filter do |raw_item_attributes|
  case raw_item_attributes['class_name']
  when "A" then Model_A
  when "B" then Model_B
  else
    nil
  end
end.complete!


220
221
222
223
# File 'lib/aws-record/record/buildable_search.rb', line 220

def multi_model_filter(proc = nil, &block)
  @params[:model_filter] = proc || block
  self
end

#on_index(index) ⇒ Object

If you are querying or scanning on an index, you can specify it with this builder method. Provide the symbol of your index as defined on your model class.



25
26
27
28
# File 'lib/aws-record/record/buildable_search.rb', line 25

def on_index(index)
  @params[:index_name] = index
  self
end

#parallel_scan(opts) ⇒ Object

For the scan operation, you can split your scan into multiple segments to be scanned in parallel. If you wish to do this, you can use this builder method to provide the :total_segments of your parallel scan and the :segment number of this scan.



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/aws-record/record/buildable_search.rb', line 41

def parallel_scan(opts)
  unless @operation == :scan
    raise ArgumentError.new("parallel_scan is only supported for scans")
  end
  unless opts[:total_segments] && opts[:segment]
    raise ArgumentError.new("Must specify :total_segments and :segment in a parallel scan.")
  end
  @params[:total_segments] = opts[:total_segments]
  @params[:segment] = opts[:segment]
  self
end

#projection_expr(statement_str) ⇒ Object

Allows you to define a projection expression for the values returned by a query or scan. See the Amazon DynamoDB Developer Guide for more details on projection expressions. You can use the symbols from your aws-record model class in a projection expression. Keys are always retrieved.

Examples:

Scan with a projection expression:

# Example model class
class ExampleTable
  include Aws::Record
  string_attr  :uuid, hash_key: true
  integer_attr :id,   range_key: true
  string_attr  :body
  map_attr     :metadata
end

scan = ExampleTable.build_scan.projection_expr(
  ":body"
).complete!


164
165
166
167
168
169
170
171
172
173
# File 'lib/aws-record/record/buildable_search.rb', line 164

def projection_expr(statement_str)
  names = @params[:expression_attribute_names]
  if names.nil?
    @params[:expression_attribute_names] = {}
    names = @params[:expression_attribute_names]
  end
  prepared = _key_pass(statement_str, names)
  @params[:projection_expression] = prepared
  self
end

#scan_ascending(b) ⇒ Object

For a query operation, you can use this to set if you query is in ascending or descending order on your range key. By default, a query is run in ascending order.



56
57
58
59
60
61
62
# File 'lib/aws-record/record/buildable_search.rb', line 56

def scan_ascending(b)
  unless @operation == :query
    raise ArgumentError.new("scan_ascending is only supported for queries.")
  end
  @params[:scan_index_forward] = b
  self
end