Dynamodb2 Table.get_item()抛出ValidationException“键上的条件数无效”

时间:2015-04-15 14:31:58

标签: python amazon-dynamodb boto

我只是在DynamoDB中执行一项简单的任务:

  1. 创建表格,
  2. 向其添加项目
  3. 查询该项目的表格。
  4. 这是我正在使用的脚本:

    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提到可以使用 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 个答案:

答案 0 :(得分:22)

DynamoDB中的

GetItem需要与键数相同数量的关键条件,主要是因为操作必须在表中找到确切的项。对于主键,您必须提供所有属性。只有一个项目(如果有)与获取期望相匹配。这是用DynamoDB doc写的。

相比之下,您可以使用Query获取给定条件的多个(可能)项目。既然你知道我相信,我认为你错误地使用了错误的get_item() api,而不是query()或类似的东西。