Class: AWS::SimpleDB::ItemCollection

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/aws/simple_db/item_collection.rb

Overview

Represents a collection of items in a SimpleDB domain.

Constant Summary collapse

OUTSIDE_QUOTES_REGEX =

Identifies quoted regions in the string, giving access to the regions before and after each quoted region, for example:

"? ? `foo?``bar?` ? 'foo?' ?".scan(OUTSIDE_QUOTES_REGEX)
# => [["? ? ", "`foo?``bar?`", " ? "], ["", "'foo?'", " ?"]]
Regexp.compile('([^\'"`]*)(`(?:[^`]*(?:``))*[^`]*`|'+
'\'(?:[^\']*(?:\'\'))*[^\']*\'|'+
'"(?:[^"]*(?:""))*[^"]*")([^\'`"]*)')

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

Parameters:

  • domain (Domain)

    The domain that you want an item collection for.



40
41
42
43
44
45
46
47
48
# File 'lib/aws/simple_db/item_collection.rb', line 40

def initialize domain, options = {}
  @domain = domain
  @conditions = []
  @conditions += options[:conditions] if options[:conditions]
  @sort_instructions = options[:sort_instructions] if options[:sort_instructions]
  @not_null_attribute = options[:not_null_attribute]
  @limit = options[:limit] if options[:limit]
  super
end

Instance Attribute Details

#domainDomain (readonly)

Returns The domain the items belong to.

Returns:

  • (Domain)

    The domain the items belong to.



51
52
53
# File 'lib/aws/simple_db/item_collection.rb', line 51

def domain
  @domain
end

Instance Method Details

#[](item_name) ⇒ Item

Note:

This does not make a request to SimpleDB.

Retuns an item with the given name.

You can ask for any item. The named item may or may not actually exist in SimpleDB.

Examples:

Get an item by symbol or string name


item = domain.items[:itemname]
item = domain.items['itemname']

Parameters:

  • item_name (String, Symbol)

    name of the item to get.

Returns:

  • (Item)

    Returns an item with the given name.



85
86
87
# File 'lib/aws/simple_db/item_collection.rb', line 85

def [] item_name
  Item.new(domain, item_name.to_s)
end

#count(options = {}, &block) ⇒ Object Also known as: size

Counts the items in the collection.

domain.items.count

You can use this method to get the total number of items in the domain, or you can use it with #where to count a subset of items. For example, to count the items where the “color” attribute is “red”:

domain.items.where("color" => "red").count

You can also limit the number of items searched using the #limit method. For example, to count the number of items up to 500:

domain.items.limit(500).count

Parameters:

  • options (Hash) (defaults to: {})

    Options for counting items.

Options Hash (options):

  • :consistent_read (Boolean) — default: false

    Causes this method to yield the most current data in the domain.

  • :where (Object)

    Restricts the item collection using #where before querying.

  • :limit (Integer)

    The maximum number of items to fetch from SimpleDB. More than one request may be required to satisfy the limit.



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/aws/simple_db/item_collection.rb', line 240

def count options = {}, &block
  return if handle_query_options(:count, options, &block)

  options = options.merge(:output_list => "count(*)")

  count = 0
  next_token = nil

  while limit.nil? || count < limit and
      response = select_request(options, next_token)

    if domain_item = response.items.first and
        count_attribute = domain_item.attributes.first
      count += count_attribute.value.to_i
    end

    next_token = response.next_token
    break unless next_token

  end

  count
end

#create(item_name, attribute_hash) ⇒ Item

Creates a new item in SimpleDB with the given attributes:

domain.items.create('shirt', {
  'colors' => ['red', 'blue'],  
  'category' => 'clearance'})

Parameters:

  • item_name (String)

    The name of the item as you want it stored in SimpleDB.

  • attribute_hash (Hash)

    A hash of attribute names and values you want to store in SimpleDB.

Returns:

  • (Item)

    Returns a reference to the object that was created.



65
66
67
68
69
# File 'lib/aws/simple_db/item_collection.rb', line 65

def create item_name, *args
  item = self[item_name]
  item.attributes.replace(*args)
  item
end

#each(options = {}) {|item| ... } ⇒ nil

Yields to the block once for each item in the domain.

Examples:

using each to fetch every item in the domain.


domain.items.each do |item|
  puts item.name
end

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :select (Symbol or Array)

    Causes this method to behave like #select and yield AWS::SimpleDB::ItemData instead of AWS::SimpleDB::Item instances.

  • :batch_size (Object)

    Specifies a maximum number of records to fetch from SimpleDB in a single request. SimpleDB may return fewer items than :batch_size per request, but never more.

Yields:

  • (item)

    Yields once for every item in the #domain.

Yield Parameters:

Returns:

  • (nil)


108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/aws/simple_db/item_collection.rb', line 108

def each options = {}, &block

  return if handle_query_options(:each, options, &block)

  if attributes = options.delete(:select)
    return select(attributes, options, &block)
  end

  perform_select(options) do |response|
    response.items.each do |item|
      yield(self[item.name])
    end
  end

end

#limitInteger #limit(value) ⇒ ItemCollection

Limits the number of items that are returned or yielded. For example, to get the 100 most popular item names:

domain.items.
  order(:popularity, :desc).
  limit(100).
  map(&:name)

Overloads:

  • #limitInteger

    Returns the current limit for the collection.

    Returns:

    • (Integer)

      Returns the current limit for the collection.

  • #limit(value) ⇒ ItemCollection

    Returns a collection with the given limit.

    Returns:



398
399
400
401
# File 'lib/aws/simple_db/item_collection.rb', line 398

def limit(*args)
  return @limit if args.empty?
  collection_with(:limit => Integer(args.first))
end

#order(attribute, order = nil) ⇒ ItemCollection

Changes the order in which results are returned or yielded. For example, to get item names in descending order of popularity, you can do:

domain.items.order(:popularity, :desc).map(&:name)

Parameters:

  • attribute (String or Symbol)

    The attribute name to order by.

  • order (String or Symbol) (defaults to: nil)

    The desired order, which may be:

    • asc or ascending (the default)

    • desc or descending

Returns:

  • (ItemCollection)

    Returns a new item collection with the given ordering logic.



378
379
380
381
382
383
384
# File 'lib/aws/simple_db/item_collection.rb', line 378

def order(attribute, order = nil)
  sort = coerce_attribute(attribute)
  sort += " DESC" if order.to_s =~ /^desc(ending)?$/
  sort += " ASC" if order.to_s =~ /^asc(ending)?$/
  collection_with(:sort_instructions => sort,
                  :not_null_attribute => attribute.to_s)
end

#select(*attribute_names, options = {}) ⇒ Object

Retrieves data from each item in the domain.

domain.items.select('size', 'color')

You may optionally filter by a set of conditions. For example, to retrieve the attributes of each of the top 100 items in order of descending popularity as an array of hashes, you could do:

items.order(:popularity, :desc).limit(100).select do |data|
  puts data.to_yaml
end

You can select specific attributes; for example, to get all the unique colors in the collection you could do:

colors = Set.new
items.select(:color) {|data| colors += data.attributes["color"] }

Finally, you can specify conditions, sort instructions, and a limit in the same method call:

items.select(:color,
             :where => "rating > 4",
             :order => [:popularity, :desc],
             :limit => 100) do |data|
  puts "Data for #{data.name}: #{data.attributes.inspect}"
end

Returns If no block is given, an enumerator is returned. If a block was passed then nil is returned.

Parameters:

  • *attributes (Symbol, String, or Array)

    The attributes to retrieve. This can be:

    • :all to retrieve all attributes (the default).

    • a Symbol or String to retrieve a single attribute.

    • an array of Symbols or Strings to retrieve multiple attributes.

    For single attributes or arrays of attributes, the attribute name may contain any characters that are valid in a SimpleDB attribute name; this method will handle escaping them for inclusion in the query. Note that you cannot use this method to select the number of items; use #count instead.

  • options (Hash) (defaults to: {})

    Options for querying the domain.

Options Hash (options):

  • :consistent_read (Boolean) — default: false

    Causes this method to yield the most current data in the domain.

  • :where (Object)

    Restricts the item collection using #where before querying.

  • :order (Object)

    Changes the order in which the items will be yielded (see #order).

  • :limit (Integer)

    The maximum number of items to fetch from SimpleDB. More than one request may be required to satisfy the limit.

  • :batch_size (Object)

    Specifies a maximum number of records to fetch from SimpleDB in a single request. SimpleDB may return fewer items than :batch_size per request, but never more.

Returns:

  • If no block is given, an enumerator is returned. If a block was passed then nil is returned.



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/aws/simple_db/item_collection.rb', line 182

def select *attributes, &block
  
  options = attributes.last.is_a?(Hash) ? attributes.pop : {}

  args = attributes + [options]

  return if handle_query_options(:select, *args, &block)

  unless block_given?
    return Enumerator.new(self, :select, *args)
  end
  
  if attributes.empty?
    output_list = '*'
  #elsif attributes == ['*']
  #  output_list = '*'
  else
    output_list = [attributes].flatten.collect do |attr|
      coerce_attribute(attr)
    end.join(', ')
  end

  perform_select(options.merge(:output_list => output_list)) do |response|
    response.items.each do |item|
      yield(ItemData.new(:domain => domain, :response_object => item))
    end
  end

  nil

end

#where(conditions, *substitutions) ⇒ ItemCollection

Returns an item collection defined by the given conditions in addition to any conditions defined on this collection. For example:

items = domain.items.where(:color => 'blue').
  where('engine_type is not null')

# does SELECT itemName() FROM `mydomain`
#      WHERE color = "blue" AND engine_type is not null
items.each { |i| ... }

Hash Conditions

When conditions is a hash, each entry produces a condition on the attribute named in the hash key. For example:

# produces "WHERE `foo` = 'bar'"
domain.items.where(:foo => 'bar')

You can pass an array value to use an “IN” operator instead of “=”:

# produces "WHERE `foo` IN ('bar', 'baz')"
domain.items.where(:foo => ['bar', 'baz'])

You can also pass a range value to use a “BETWEEN” operator:

# produces "WHERE `foo` BETWEEN 'bar' AND 'baz'
domain.items.where(:foo => 'bar'..'baz')

# produces "WHERE (`foo` >= 'bar' AND `foo` < 'baz')"
domain.items.where(:foo => 'bar'...'baz')

Placeholders

If conditions is a string and “?” appears outside of any quoted part of the expression, placeholers is expected to contain a value for each of the “?” characters in the expression. For example:

# produces "WHERE foo like 'fred''s % value'"
domain.items.where("foo like ?", "fred's % value")

Array values are surrounded with parentheses when they are substituted for a placeholder:

# produces "WHERE foo in ('1', '2')"
domain.items.where("foo in ?", [1, 2])

Note that no substitutions are made within a quoted region of the query:

# produces "WHERE `foo?` = 'red'"
domain.items.where("`foo?` = ?", "red")

# produces "WHERE foo = 'fuzz?' AND bar = 'zap'"
domain.items.where("foo = 'fuzz?' AND bar = ?", "zap")

Also note that no attempt is made to correct for syntax:

# produces "WHERE 'foo' = 'bar'", which is invalid
domain.items.where("? = 'bar'", "foo")

Returns:

  • (ItemCollection)

    Returns a new item collection with the additional conditions.



338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/aws/simple_db/item_collection.rb', line 338

def where(conditions, *substitutions)
  case conditions
  when String
    conditions = [replace_placeholders(conditions, *substitutions)]
  when Hash
    conditions = conditions.map do |name, value|
      name = coerce_attribute(name)
      case value
      when Array
        "#{name} IN " + coerce_substitution(value)
      when Range
        if value.exclude_end?
          "(#{name} >= #{coerce_substitution(value.begin)} AND " +
            "#{name} < #{coerce_substitution(value.end)})"
        else
          "#{name} BETWEEN #{coerce_substitution(value.begin)} AND " +
            coerce_substitution(value.end)
        end
      else
        "#{name} = " + coerce_substitution(value)
      end
    end
  end

  collection_with(:conditions => self.conditions + conditions)
end