web-dev-qa-db-ja.com

Dynamodb2 Table.get_item()はValidationExceptionをスローします "キーの条件の数が無効です"

DynamoDBで簡単なタスクを実行しています。

  1. テーブルを作成し、
  2. それにアイテムを追加します
  3. そのアイテムのテーブルをクエリします。

これが私が使用しているスクリプトです:

from boto.dynamodb2.fields import HashKey, RangeKey, AllIndex, GlobalAllIndex
from boto.dynamodb2.items import Item
from boto.dynamodb2.layer1 import DynamoDBConnection
from boto.dynamodb2.table import Table

# Using DynamoDB Local
conn = DynamoDBConnection(Host='localhost', port=8000, is_secure=False)

## ----- Create a table -----
throughput = {
    'write': 1,
    'read': 1
}

schema = [
    HashKey('id'),
    RangeKey('rating')
]

local_indexes = [
    AllIndex('local_all_index_seats', parts=[
        HashKey('id'),
        RangeKey('seats')
    ])
]

global_indexes = [
    GlobalAllIndex('global_all_index_color', parts=[
        HashKey('color'),
        RangeKey('rating')
    ])
]

new_table = Table.create('items', schema=schema, indexes=local_indexes,
                         global_indexes=global_indexes, connection=conn,
                         throughput=throughput)
print 'Table created'
## -------- Table created ---------

## -------- Add an item --------

items_table = Table('items', connection=conn)  # New reference to the table we created

new_item_data = {
    "category": "Sofa",
    "rating": "4",
    "color": "beige",
    "seats": "6",
    "id": "first_id"
}

new_item = Item(items_table, new_item_data)
new_item.save()
print 'New item saved'
## -------- Item added --------

## -------- Query Item --------

items_table = Table('items', connection=conn)  # New reference to the table we created
queried_item = items_table.get_item(id='first_id')
print 'Query done. Category is: {}'.format(queried_item['Category'])

## -------- Querying Done --------

このスクリプトを実行すると、ValidationExceptionが表示されます。

(backend)aniket [~/PycharmProjects/website_backend] -> python reproduce.py                                                                                 ±[●●][master]
Table created
New item saved
Traceback (most recent call last):
  File "reproduce.py", line 59, in <module>
    queried_item = items_table.get_item(id='first_id')
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/table.py", line 705, in get_item
    consistent_read=consistent
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 1099, in get_item
    body=json.dumps(params))
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 2842, in make_request
    retry_handler=self._retry_handler)
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/connection.py", line 954, in _mexe
    status = retry_handler(response, i, next_sleep)
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 2882, in _retry_handler
    response.status, response.reason, data)
boto.dynamodb2.exceptions.ValidationException: ValidationException: 400 Bad Request
{u'Message': u'The number of conditions on the keys is invalid', u'__type': u'com.Amazon.coral.validate#ValidationException'}

私は何か間違ったことをしていると確信していますが、何が起こっているのか理解できません。 DynamoDB Docsは、only HashKeyを使用してクエリを実行できると述べているため、私が行っていることはかなり正常なようです。

それが役立つ場合に備えて、デバッグログも追加しました。出力は次のとおりです。

(backend)aniket [~/PycharmProjects/website_backend] -> python reproduce.py                                                                                 ±[●●][master]
2015-04-15 20:04:48,218 [DEBUG] (boto) Using access key found in shared credential file.
2015-04-15 20:04:48,218 [DEBUG] (boto) Using secret key found in shared credential file.
2015-04-15 20:04:48,219 [DEBUG] (boto) Method: POST
2015-04-15 20:04:48,219 [DEBUG] (boto) Path: /
2015-04-15 20:04:48,219 [DEBUG] (boto) Data: {"GlobalSecondaryIndexes": [{"KeySchema": [{"KeyType": "HASH", "AttributeName": "color"}, {"KeyType": "RANGE", "AttributeName": "rating"}], "IndexName": "global_all_index_color", "Projection": {"ProjectionType": "ALL"}, "ProvisionedThroughput": {"WriteCapacityUnits": 5, "ReadCapacityUnits": 5}}], "AttributeDefinitions": [{"AttributeName": "id", "AttributeType": "S"}, {"AttributeName": "rating", "AttributeType": "S"}, {"AttributeName": "seats", "AttributeType": "S"}, {"AttributeName": "color", "AttributeType": "S"}], "LocalSecondaryIndexes": [{"KeySchema": [{"KeyType": "HASH", "AttributeName": "id"}, {"KeyType": "RANGE", "AttributeName": "seats"}], "IndexName": "local_all_index_seats", "Projection": {"ProjectionType": "ALL"}}], "ProvisionedThroughput": {"WriteCapacityUnits": 1, "ReadCapacityUnits": 1}, "TableName": "items", "KeySchema": [{"KeyType": "HASH", "AttributeName": "id"}, {"KeyType": "RANGE", "AttributeName": "rating"}]}
2015-04-15 20:04:48,219 [DEBUG] (boto) Headers: {'Host': 'localhost', 'Content-Type': 'application/x-amz-json-1.0', 'Content-Length': '942', 'X-Amz-Target': 'DynamoDB_20120810.CreateTable'}
2015-04-15 20:04:48,219 [DEBUG] (boto) Host: localhost
2015-04-15 20:04:48,219 [DEBUG] (boto) Port: 8000
2015-04-15 20:04:48,219 [DEBUG] (boto) Params: {}
2015-04-15 20:04:48,219 [DEBUG] (boto) establishing HTTP connection: kwargs={'port': 8000, 'timeout': 70}
2015-04-15 20:04:48,219 [DEBUG] (boto) Token: None
2015-04-15 20:04:48,219 [DEBUG] (boto) CanonicalRequest:
POST
/

Host:localhost
x-amz-date:20150415T143448Z
x-amz-target:DynamoDB_20120810.CreateTable

Host;x-amz-date;x-amz-target
4d4b471da224cff0353d444ba9f31ecbda7ac332b618c8db038940477cf5fbd9
2015-04-15 20:04:48,219 [DEBUG] (boto) StringToSign:
AWS4-HMAC-SHA256
20150415T143448Z
20150415/localhost/localhost/aws4_request
a54fd62c95217cf6fafe69876388ac3ae8ffd4b2d87e23f71a131741d3e64792
2015-04-15 20:04:48,219 [DEBUG] (boto) Signature:
51e3035fcfef8b31f8d6c0e22779ba4b17990d3f91f8dfda6b70e559ee5c384e
2015-04-15 20:04:48,220 [DEBUG] (boto) Final headers: {'Content-Length': '942', 'User-Agent': 'Boto/2.38.0 Python/2.7.6 Linux/3.16.0-30-generic', 'Host': 'localhost', 'X-Amz-Date': '20150415T143448Z', 'X-Amz-Target': 'DynamoDB_20120810.CreateTable', 'Content-Type': 'application/x-amz-json-1.0', 'Authorization': 'AWS4-HMAC-SHA256 Credential=AKIAJW2Q5MT375WFZIMA/20150415/localhost/localhost/aws4_request,SignedHeaders=Host;x-amz-date;x-amz-target,Signature=51e3035fcfef8b31f8d6c0e22779ba4b17990d3f91f8dfda6b70e559ee5c384e'}
2015-04-15 20:04:49,004 [DEBUG] (boto) Response headers: [('x-amzn-requestid', 'e4cd23ec-ad5a-4f94-8d80-dd9f002b0f28'), ('content-length', '1160'), ('content-type', 'application/x-amz-json-1.0'), ('x-amz-crc32', '175075191'), ('server', 'Jetty(8.1.12.v20130726)')]
2015-04-15 20:04:49,004 [DEBUG] (boto) Saw HTTP status: 200
2015-04-15 20:04:49,004 [DEBUG] (boto) Validating crc32 checksum for body: {"TableDescription":{"AttributeDefinitions":[{"AttributeName":"id","AttributeType":"S"},{"AttributeName":"rating","AttributeType":"S"},{"AttributeName":"seats","AttributeType":"S"},{"AttributeName":"color","AttributeType":"S"}],"TableName":"items","KeySchema":[{"AttributeName":"id","KeyType":"HASH"},{"AttributeName":"rating","KeyType":"RANGE"}],"TableStatus":"ACTIVE","CreationDateTime":1429108488.651,"ProvisionedThroughput":{"LastIncreaseDateTime":0.000,"LastDecreaseDateTime":0.000,"NumberOfDecreasesToday":0,"ReadCapacityUnits":1,"WriteCapacityUnits":1},"TableSizeBytes":0,"ItemCount":0,"LocalSecondaryIndexes":[{"IndexName":"local_all_index_seats","KeySchema":[{"AttributeName":"id","KeyType":"HASH"},{"AttributeName":"seats","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"},"IndexSizeBytes":0,"ItemCount":0}],"GlobalSecondaryIndexes":[{"IndexName":"global_all_index_color","KeySchema":[{"AttributeName":"color","KeyType":"HASH"},{"AttributeName":"rating","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"},"IndexStatus":"ACTIVE","ProvisionedThroughput":{"ReadCapacityUnits":5,"WriteCapacityUnits":5},"IndexSizeBytes":0,"ItemCount":0}]}}
2015-04-15 20:04:49,004 [DEBUG] (boto) {"TableDescription":{"AttributeDefinitions":[{"AttributeName":"id","AttributeType":"S"},{"AttributeName":"rating","AttributeType":"S"},{"AttributeName":"seats","AttributeType":"S"},{"AttributeName":"color","AttributeType":"S"}],"TableName":"items","KeySchema":[{"AttributeName":"id","KeyType":"HASH"},{"AttributeName":"rating","KeyType":"RANGE"}],"TableStatus":"ACTIVE","CreationDateTime":1429108488.651,"ProvisionedThroughput":{"LastIncreaseDateTime":0.000,"LastDecreaseDateTime":0.000,"NumberOfDecreasesToday":0,"ReadCapacityUnits":1,"WriteCapacityUnits":1},"TableSizeBytes":0,"ItemCount":0,"LocalSecondaryIndexes":[{"IndexName":"local_all_index_seats","KeySchema":[{"AttributeName":"id","KeyType":"HASH"},{"AttributeName":"seats","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"},"IndexSizeBytes":0,"ItemCount":0}],"GlobalSecondaryIndexes":[{"IndexName":"global_all_index_color","KeySchema":[{"AttributeName":"color","KeyType":"HASH"},{"AttributeName":"rating","KeyType":"RANGE"}],"Projection":{"ProjectionType":"ALL"},"IndexStatus":"ACTIVE","ProvisionedThroughput":{"ReadCapacityUnits":5,"WriteCapacityUnits":5},"IndexSizeBytes":0,"ItemCount":0}]}}
Table created
2015-04-15 20:04:49,004 [DEBUG] (boto) Method: POST
2015-04-15 20:04:49,004 [DEBUG] (boto) Path: /
2015-04-15 20:04:49,004 [DEBUG] (boto) Data: {"Expected": {"category": {"Exists": false}, "rating": {"Exists": false}, "id": {"Exists": false}, "color": {"Exists": false}, "seats": {"Exists": false}}, "Item": {"category": {"S": "Sofa"}, "rating": {"S": "4"}, "id": {"S": "first_id"}, "color": {"S": "beige"}, "seats": {"S": "6"}}, "TableName": "items"}
2015-04-15 20:04:49,004 [DEBUG] (boto) Headers: {'Host': 'localhost', 'Content-Type': 'application/x-amz-json-1.0', 'Content-Length': '307', 'X-Amz-Target': 'DynamoDB_20120810.PutItem'}
2015-04-15 20:04:49,005 [DEBUG] (boto) Host: localhost
2015-04-15 20:04:49,005 [DEBUG] (boto) Port: 8000
2015-04-15 20:04:49,005 [DEBUG] (boto) Params: {}
2015-04-15 20:04:49,005 [DEBUG] (boto) Token: None
2015-04-15 20:04:49,005 [DEBUG] (boto) CanonicalRequest:
POST
/

Host:localhost
x-amz-date:20150415T143449Z
x-amz-target:DynamoDB_20120810.PutItem

Host;x-amz-date;x-amz-target
96fd2aee6eabd2c812d7111c9a47ba21c31ccc86859c963cfa3fd69a18edc957
2015-04-15 20:04:49,005 [DEBUG] (boto) StringToSign:
AWS4-HMAC-SHA256
20150415T143449Z
20150415/localhost/localhost/aws4_request
9ed70485aa9e7036fd2db89e34036c9e24a3c91b6e35dbb7fc2cd476b4766f21
2015-04-15 20:04:49,005 [DEBUG] (boto) Signature:
1d81bae229584b7466c6951a71010c8e2d7a441e80b2e9b5a60d9782859345dc
2015-04-15 20:04:49,005 [DEBUG] (boto) Final headers: {'Content-Length': '307', 'User-Agent': 'Boto/2.38.0 Python/2.7.6 Linux/3.16.0-30-generic', 'Host': 'localhost', 'X-Amz-Date': '20150415T143449Z', 'X-Amz-Target': 'DynamoDB_20120810.PutItem', 'Content-Type': 'application/x-amz-json-1.0', 'Authorization': 'AWS4-HMAC-SHA256 Credential=AKIAJW2Q5MT375WFZIMA/20150415/localhost/localhost/aws4_request,SignedHeaders=Host;x-amz-date;x-amz-target,Signature=1d81bae229584b7466c6951a71010c8e2d7a441e80b2e9b5a60d9782859345dc'}
2015-04-15 20:04:49,287 [DEBUG] (boto) Response headers: [('x-amzn-requestid', '80571386-1ce7-4f9b-84fb-6805a0dfa171'), ('content-length', '2'), ('content-type', 'application/x-amz-json-1.0'), ('x-amz-crc32', '2745614147'), ('server', 'Jetty(8.1.12.v20130726)')]
2015-04-15 20:04:49,287 [DEBUG] (boto) Saw HTTP status: 200
2015-04-15 20:04:49,287 [DEBUG] (boto) Validating crc32 checksum for body: {}
2015-04-15 20:04:49,287 [DEBUG] (boto) {}
New item saved
2015-04-15 20:04:49,288 [DEBUG] (boto) Method: POST
2015-04-15 20:04:49,288 [DEBUG] (boto) Path: /
2015-04-15 20:04:49,288 [DEBUG] (boto) Data: {"ConsistentRead": false, "TableName": "items", "Key": {"id": {"S": "first_id"}}}
2015-04-15 20:04:49,288 [DEBUG] (boto) Headers: {'Host': 'localhost', 'Content-Type': 'application/x-amz-json-1.0', 'Content-Length': '81', 'X-Amz-Target': 'DynamoDB_20120810.GetItem'}
2015-04-15 20:04:49,289 [DEBUG] (boto) Host: localhost
2015-04-15 20:04:49,289 [DEBUG] (boto) Port: 8000
2015-04-15 20:04:49,289 [DEBUG] (boto) Params: {}
2015-04-15 20:04:49,289 [DEBUG] (boto) Token: None
2015-04-15 20:04:49,289 [DEBUG] (boto) CanonicalRequest:
POST
/

Host:localhost
x-amz-date:20150415T143449Z
x-amz-target:DynamoDB_20120810.GetItem

Host;x-amz-date;x-amz-target
1563f0044c8fc746bb9a0ec2e4754e5fd03e62d604102f0745920d8c49481e88
2015-04-15 20:04:49,289 [DEBUG] (boto) StringToSign:
AWS4-HMAC-SHA256
20150415T143449Z
20150415/localhost/localhost/aws4_request
059601773b2e09d4c42f984cb185bf565e47a9dff8d42b3ae15dd61b4fc41f76
2015-04-15 20:04:49,289 [DEBUG] (boto) Signature:
e22cfe8b3e3e03dfa4e05ec11f333f9aaff0edcdbf498ebfa9d0e7dc5b452916
2015-04-15 20:04:49,290 [DEBUG] (boto) Final headers: {'Content-Length': '81', 'User-Agent': 'Boto/2.38.0 Python/2.7.6 Linux/3.16.0-30-generic', 'Host': 'localhost', 'X-Amz-Date': '20150415T143449Z', 'X-Amz-Target': 'DynamoDB_20120810.GetItem', 'Content-Type': 'application/x-amz-json-1.0', 'Authorization': 'AWS4-HMAC-SHA256 Credential=AKIAJW2Q5MT375WFZIMA/20150415/localhost/localhost/aws4_request,SignedHeaders=Host;x-amz-date;x-amz-target,Signature=e22cfe8b3e3e03dfa4e05ec11f333f9aaff0edcdbf498ebfa9d0e7dc5b452916'}
2015-04-15 20:04:49,315 [DEBUG] (boto) Response headers: [('x-amzn-requestid', '51547354-f266-4870-8c79-6192e7d7c7b5'), ('content-length', '118'), ('content-type', 'application/x-amz-json-1.0'), ('server', 'Jetty(8.1.12.v20130726)')]
2015-04-15 20:04:49,316 [DEBUG] (boto) Saw HTTP status: 400
2015-04-15 20:04:49,316 [DEBUG] (boto) {"__type":"com.Amazon.coral.validate#ValidationException","Message":"The number of conditions on the keys is invalid"}
Traceback (most recent call last):
  File "reproduce.py", line 71, in <module>
    queried_item = items_table.get_item(id='first_id')
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/table.py", line 705, in get_item
    consistent_read=consistent
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 1099, in get_item
    body=json.dumps(params))
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 2842, in make_request
    retry_handler=self._retry_handler)
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/connection.py", line 954, in _mexe
    status = retry_handler(response, i, next_sleep)
  File "/home/aniket/venv/backend/local/lib/python2.7/site-packages/boto/dynamodb2/layer1.py", line 2882, in _retry_handler
    response.status, response.reason, data)
boto.dynamodb2.exceptions.ValidationException: ValidationException: 400 Bad Request
{u'Message': u'The number of conditions on the keys is invalid', u'__type': u'com.Amazon.coral.validate#ValidationException'}
12
czardoz

DynamoDBのGetItemには、キーの数と同じ数のキー条件が必要です。これは主に、操作でテーブル内の正確なアイテムを見つける必要があるためです。主キーには、すべての属性を指定する必要があります。 Getの期待に一致するアイテムは、ある場合は1つだけにする必要があります。これは DynamoDB doc に記述されています。

対照的に、Queryを使用して、特定の条件に対して複数の(場合によっては)アイテムを取得できます。私が信じていることを知っているので、get_item()などの代わりに間違ったquery()apiを誤って使用したと思います。

22
Mingliang Liu