Class: Aws::Dynamodb::Query::Query
- Inherits:
-
Object
- Object
- Aws::Dynamodb::Query::Query
- Defined in:
- lib/aws/dynamodb/query.rb
Class Method Summary collapse
Class Method Details
.call(table_name, model_class: nil, nullify_model_attributes: false, result_type: Struct, index_name: nil, select: nil, key_condition_expression: nil, expression_attribute_names: nil, expression_attribute_values: nil, scan_index_forward: true, return_consumed_capacity: nil, pagination: false, last_evaluated_key: nil, aws_region: ENV['AWS_REGION'], aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'], aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], aws_dynamodb_endpoint: ENV['aws_dynamodb_endpoint']) ⇒ Array
Queries Dynamodb for items.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/aws/dynamodb/query.rb', line 34 def self.call(table_name, model_class: nil, nullify_model_attributes: false, result_type: Struct, index_name: nil, select: nil, key_condition_expression: nil, expression_attribute_names: nil, expression_attribute_values: nil, scan_index_forward: true, return_consumed_capacity: nil, pagination: false, last_evaluated_key: nil, aws_region: ENV['AWS_REGION'], aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'], aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], aws_dynamodb_endpoint: ENV['aws_dynamodb_endpoint']) result = [] # DyanmoDB Query results are divided into "pages" of data that are 1 MB in size (or less). # Agents data exceeds 1MB so we need multiple pages. # @see http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.Pagination last_evaluated_key = last_evaluated_key loop do payload = { TableName: table_name } # optional query parameters payload[:IndexName] = index_name if index_name payload[:select] = select if select payload[:KeyConditionExpression] = key_condition_expression if key_condition_expression payload[:ExpressionAttributeNames] = expression_attribute_names if expression_attribute_names payload[:ExpressionAttributeValues] = expression_attribute_values if expression_attribute_values payload[:scan_index_forward] = scan_index_forward if scan_index_forward payload[:ReturnConsumedCapacity] = return_consumed_capacity if return_consumed_capacity payload[:ExclusiveStartKey] = last_evaluated_key if last_evaluated_key # generate AWS Authorization header aws_signature = Aws::Signature::V4::Signature.new(aws_region, aws_access_key_id, aws_secret_access_key) aws_signature.generate_signature('dynamodb', 'DynamoDB_20120810.Query', 'POST', payload, aws_dynamodb_endpoint, '/') # Create the HTTP objects uri = URI.parse(aws_dynamodb_endpoint) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = aws_dynamodb_endpoint.include?('https') request = Net::HTTP::Post.new(uri.request_uri, aws_signature.headers) request.body = payload.to_json res = http.request(request) # error => return empty array unless res.is_a? Net::HTTPSuccess Rails.logger.error "Error querying DynamoDB: code=#{res.code} message=#{res.} body=#{res.body}" if defined? Rails # jsonapi error format result = { errors: [ status: res.code, title: res., detail: res.body ] } return result end # Create DAO struct object <struct Struct::Customer id> Struct.new('AwsDynamodbQueryDAO', *model_class.attributes.attributes.keys) if result_type.eql? Struct # success => parse returned json json = Yajl::Parser.new.parse(res.body) # extract and construct resultset array json['Items'].each do |item| record = {} stored_attributes = [] item.keys.each do |key| # @see: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_AttributeValue.html # Sample dynamodb item: {"date_joined"=>{"S"=>"2017-09-30T16:00:00+00:00"}, "contact_country_code"=>{"NULL"=>true}, "full_name"=>{"S"=>"Breena"}, "has_bank_swift"=>{"BOOL"=>false}} # NULL will fall back to default nil # Number will be handled afterwards dynamodb_data_types = %w[S BS L M NS S SS BOOL] # value could be found in one of these data types key_dasherized = key.to_s.dasherize dynamodb_data_types.each do |data_type| record[key_dasherized] = record[key_dasherized] || item[key][data_type] end # handle numbers: integer or float value = item[key]['N'] if record[key_dasherized].nil? and value.present? begin record[key_dasherized] = Integer(value) rescue ArgumentError record[key_dasherized] = Float(value) end end stored_attributes += [key.to_sym] end # nullify remaining model attributes to be included in returned result if nullify_model_attributes and model_class.respond_to? :attributes unset_attributes = model_class.attributes.attributes.keys - stored_attributes unset_attributes.each do |attr| record[attr.to_s.dasherize] = nil end end case result_type.to_s when Struct.to_s # order values in the same order as model attribute_keys attribute_values = [] model_class.attributes.attributes.keys.each do |attribute_key| attribute_values << record[attribute_key.to_s.dasherize] end result << Struct::AwsDynamodbQueryDAO.new(*attribute_values) when model_class.to_s result << model_class.new(record) else result << record end end # LastEvaluatedKey in the response indicates that not all of the items have been retrieved. # It should be used as the ExclusiveStartKey for the next Query request to retrieve the next page items. last_evaluated_key = json['LastEvaluatedKey'] # Break if pagination is enabled. Else, absence of LastEvaluatedKey indicates that there are no more pages to retrieve. break if pagination.present? || last_evaluated_key.blank? end result end |