Class: AWS::DynamoDB::ItemCollection
- Inherits:
-
Object
- Object
- AWS::DynamoDB::ItemCollection
- Includes:
- Core::Collection::Limitable, Expectations, Types
- Defined in:
- lib/aws/dynamo_db/item_collection.rb
Overview
Represents a collection of DynamoDB items.
You can use an item collection to:
Creating an Item
To create an item, just call #create with a hash of attributes.
table = dynamo_db.tables['my-table']
table.hash_key = [:id, :string]
table.items.create('id' => 'abc', 'count' => 5, 'colors' => %w(red blue))
Attribute names can be symbols/strings and values can be strings or numbers or arrays/sets of strings/numbers. The attributes must contain the hash key name/value for the item and the value must be of the correct type (e.g. string or number).
Getting an Item
To get an item, you provide the hash key
# gets a reference to the item, no request is made
item = table.items['hash-key-value']
You call methods against the item returned to get, add, update or delete attributes. See Item for more information.
Enumerating Items
You can enumerate items 2 ways:
Item objects do not have any attribute data populated. Think of them as just references to the item in Amazon DynamoDB. They only konw the objects hash key (and optional range key).
ItemData objects are wrappers around the actual item attributes.
To enumerate Item objects just call each on the item collection.
table.items.each do |item|
puts item.hash_value
end
To enumerate ItemData objects you need to specify what attributes you are interested in. This will cause #each to yield ItemData objects. Call AWS::DynamoDB::ItemData#attributes to get the hash of attribute names/values.
table.items.select('id', 'category').each do |item_data|
item_data.attributes #=> { 'id' => 'abc', 'category' => 'foo' }
end
If you want item data objects with all attributes just call select without any arguments:
# request a maximum of 10 items from Amazon DynamoDB
table.items.select.limit(10).each do |item_data|
item_data.attributes #=> { 'id' => 'abc', 'category' => 'foo', ... }
end
Please note that enumerating objects is done via the scan operation. Refer to the Amazon DynamoDB documentation for more information about scanning.
Defined Under Namespace
Classes: FilterBuilder
Constant Summary collapse
- RANGE_KEY_OPTIONS =
{ :range_less_than => "LT", :range_greater_than => "GT", :range_lte => "LE", :range_gte => "GE", :range_begins_with => "BEGINS_WITH" }
Instance Attribute Summary collapse
- #scan_filters ⇒ Object readonly
-
#table ⇒ Table
readonly
The table to which the items in the collection belong.
Attributes included from Core::Model
Instance Method Summary collapse
-
#at(hash_value, range_value = nil) ⇒ Item
(also: #[])
Returns an object representing an item in the table, identified by its hash key value and conditionally its range key value.
-
#count(options = {}) ⇒ Integer
Counts the items in the collection using a table scan.
-
#create(attributes, options = {}) ⇒ Item
(also: #put)
Creates a new item, or replaces an old item with a new item (including all the attributes).
-
#each(options = {}) {|item| ... } ⇒ Object
Iterates over all the items in the collection using a scan operation.
-
#initialize(table, opts = {}) ⇒ ItemCollection
constructor
A new instance of ItemCollection.
-
#query(options = {}, &block) ⇒ Object
Queries the items in the table by primary key values.
- #refine(opts) ⇒ Object
-
#select(*attributes, options = {}) {|data| ... } ⇒ Enumerator?
Retrieves data about the items in the collection.
- #where(filter) ⇒ Object (also: #and)
- #with_filter(attribute, op, *values) ⇒ Object
Methods included from Types
#format_attribute_value, #value_from_response, #values_from_response_hash
Methods included from Core::Collection::Limitable
Methods included from Core::Collection
#each_batch, #enum, #first, #in_groups_of, #page
Methods included from Core::Model
#client, #config_prefix, #inspect
Constructor Details
#initialize(table, opts = {}) ⇒ ItemCollection
Returns a new instance of ItemCollection.
96 97 98 99 100 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 96 def initialize(table, opts = {}) @table = table @scan_filters = opts[:scan_filters] || {} super end |
Instance Attribute Details
#scan_filters ⇒ Object (readonly)
107 108 109 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 107 def scan_filters @scan_filters end |
#table ⇒ Table (readonly)
Returns The table to which the items in the collection belong.
104 105 106 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 104 def table @table end |
Instance Method Details
#at(hash_value, range_value = nil) ⇒ Item Also known as: []
Returns an object representing an item in the table, identified by its hash key value and conditionally its range key value. This method will raise an exception unless the table has a schema loaded or configured. The type of each parameter must match the type in the table’s schema, but currently the SDK makes no attempt to validate the key elements.
table.hash_key = [:id, :string]
table.range_key = [:range, :number]
item = table.items.at("abc123", 12)
241 242 243 244 245 246 247 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 241 def at hash_value, range_value = nil table.assert_schema! if table.composite_key? and !range_value raise ArgumentError, "a range key value is required for this table" end Item.new(table, hash_value, range_value) end |
#count(options = {}) ⇒ Integer
Counts the items in the collection using a table scan. The count applies to the items that match all the filters on the collection. For example:
# count the blue items
items.where(:color => "blue").count
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 586 def count = {} = .merge(:count => true) # since each with :count yields the per-page counts, each with # :limit and :count effectively limits the number of requests, # not the number of items limit = .delete(:limit) [:limit] = .delete(:max_requests) if .key?(:max_requests) # it usually doesn't make sense to ask for more items than you # care about counting [:batch_size] ||= limit if limit enumerator().inject(0) do |sum, n| return limit if limit && sum + n >= limit sum + n end end |
#create(attributes, options = {}) ⇒ Item Also known as: put
Creates a new item, or replaces an old item with a new item (including all the attributes). If an item already exists in the specified table with the same primary key, the new item completely replaces the existing item. You can perform a conditional put (insert a new item if one with the specified primary key doesn’t exist), or replace an existing item if it has certain attribute values.
items.put(:id => "abc123", :colors => ["red", "white"])
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 167 def create attributes, = {} table.assert_schema! attributes = attributes.inject({}) do |hash, (key, value)| context = "value for attribute #{key}" hash.update(key.to_s => format_attribute_value(value, context)) end client_opts = { :table_name => table.name, :item => attributes } expected = expect_conditions() client_opts[:expected] = expected unless expected.empty? client_opts[:return_values] = [:return].to_s.upcase if [:return] resp = client.put_item(client_opts) item = Item.new_from(:put_item, attributes, table) if [:return] values_from_response_hash(resp.data["Attributes"]) else item end end |
#each(options = {}) {|item| ... } ⇒ Object
Iterates over all the items in the collection using a scan operation. A scan operation scans the entire table. You can specify filters to apply to the results to refine the values returned to you, after the complete scan. Amazon DynamoDB puts a 1MB limit on the scan (the limit applies before the results are filtered). A scan can result in no table data meeting the filter criteria.
For more information about filtering the collection see the #where method.
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 479 def each( = {}, &block) if conditions = .delete(:where) return where(conditions).each(, &block) end table.assert_schema! = .merge(:table_name => table.name) [:scan_filter] = scan_filters unless scan_filters.empty? unless [:count] or [:item_data] [:attributes_to_get] = [table.hash_key.name] [:attributes_to_get] << table.range_key.name if table.composite_key? end super(, &block) end |
#query(options = {}, &block) ⇒ Object
This method is only valid for tables with a composite primary key.
Queries the items in the table by primary key values. This operation is generally more efficient than the scan operation, which always scans the whole table. A Query operation searches for a specific range of keys satisfying a given set of key conditions and does not have the added step of filtering out results.
# find all items with a given hash key value
items.query(:hash_value => "abc123")
# get only the colors attribute of each item
items.query(
:hash_value => "abc123",
:select => [:colors])
# find only the items where the range key is between two values
items.query(
:hash_value => "abc123",
:range_value => 1..100
)
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 697 def query( = {}, &block) = .merge(:query => true) raise ArgumentError, "a hash key value is required" unless [:hash_value] [:hash_key_value] = format_attribute_value(.delete(:hash_value)) range = .delete(:range_value) range_op = nil value_list = [] if range and range.kind_of?(Range) value_list = [format_attribute_value(range.begin), format_attribute_value(range.end)] range_op = "BETWEEN" elsif range value_list = [format_attribute_value(range)] range_op = "EQ" end RANGE_KEY_OPTIONS.each do |name, op| if value = .delete(name) raise(ArgumentError, "only one range key condition is supported") if range_op range_op = op value_list = [format_attribute_value(value)] end end [:range_key_condition] = { :attribute_value_list => value_list, :comparison_operator => range_op } if range_op if select = .delete(:select) [:item_data] = true [:attributes_to_get] = select.map do |att| att.to_s end unless select == :all end if block each(, &block) else enumerator() end end |
#refine(opts) ⇒ Object
766 767 768 769 770 771 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 766 def refine(opts) opts = { :scan_filters => scan_filters }.merge(opts) self.class.new(table, opts) end |
#select(*attributes, options = {}) {|data| ... } ⇒ Enumerator?
Retrieves data about the items in the collection. This method works like #each, except that it returns or yields AWS::DynamoDB::ItemData instances instead of AWS::DynamoDB::Item instances. This is useful if you want to use the attributes of the item in a loop or retain them in memory. Also, unlike #each which always requests only the primary key attributes of the items, this method allows you to specify which attributes to retrieve from DynamoDB.
# fetch all attributes for a collection of items
items.select { |data| p data.attributes }
# fetch only the "color" attribute of each item
items.select(:color) { |data| p data.attributes["color"] }
# use client-side filtering to delete a subset of the items
items.select do |data|
data.item.delete if data.attributes.size % 2 == 0
end
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 548 def select *attributes, &block = {} = attributes.pop if attributes.last.kind_of?(Hash) = .merge(:item_data => true) [:attributes_to_get] = attributes.map { |att| att.to_s } unless attributes.empty? if block_given? each(, &block) else enumerator() end end |
#where(attributes) ⇒ ItemCollection #where(attribute_name) ⇒ FilterBuilder Also known as: and
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 441 def where(filter) case filter when Hash filter.inject(self) do |items, (name, value)| case value when nil items.with_filter(name.to_s, "NULL") when Range items.with_filter(name.to_s, "BETWEEN", value.begin, value.end) else items.with_filter(name.to_s, "EQ", value) end end when String, Symbol FilterBuilder.new(self, filter.to_s) end end |
#with_filter(attribute, op, *values) ⇒ Object
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 |
# File 'lib/aws/dynamo_db/item_collection.rb', line 748 def with_filter attribute, op, *values values = values.map {|value| format_attribute_value(value) } filter = { :attribute_value_list => values, :comparison_operator => op } if scan_filters.key?(attribute) raise(ArgumentError, "conflicting filters for attribute #{attribute}") end refine(:scan_filters => scan_filters.merge(attribute => filter)) end |