Dynamodb2 Table.get_item() 抛出 ValidationException "The number of conditions on the keys is invalid"

16

我只是在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文档提到可以仅使用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'}
1个回答

30

GetItem 在 DynamoDB 中需要与键的数量相同数量的键条件,主要是因为该操作必须找到表中精确的项目。对于主键,您必须提供所有属性。如果有任何匹配 Get 期望的一个或零个项目,则应只有一个。这在DynamoDB文档中有所说明。

相比之下,您可以使用 Query 获取给定条件的多个(可能)项目。由于您已经知道这一点,我认为您错误地使用了错误的 get_item() API,而不是 query() 或类似的内容。


有道理。出于某种原因,我认为get_item()会在内部使用查询API。 - czardoz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接