【问题标题】:Query DynamoDB with a hash key and a range key with Boto3使用 Boto3 使用哈希键和范围键查询 DynamoDB
【发布时间】:2016-01-21 08:13:57
【问题描述】:

我在使用 AWS Boto3 使用推荐的 KeyConditionExpression 同时使用哈希键和范围键查询 DynamoDB 时遇到问题。我附上了一个示例查询:

import boto3
from boto3 import dynamodb
from boto3.session import Session
dynamodb_session = Session(aws_access_key_id=AWS_KEY,
              aws_secret_access_key=AWS_PASS,
              region_name=DYNAMODB_REGION)
dynamodb = dynamodb_session.resource('dynamodb')
table=dynamodb.Table(TABLE_NAME)
request = {
    'ExpressionAttributeNames': {
        '#n0': 'hash_key',
        '#n1': 'range_key'
    },
    'ExpressionAttributeValues': {
        ':v0': {'S': MY_HASH_KEY},
        ':v1': {'N': GT_RANGE_KEY}
    },
    'KeyConditionExpression': '(#n0 = :v0) AND (#n1 > :v1)',
    'TableName': TABLE_NAME
}
response = table.query(**request)

当我使用以下方案对表运行时:

Table Name: TABLE_NAME
Primary Hash Key: hash_key (String)
Primary Range Key: range_key (Number)

我收到以下错误,我不明白为什么:

ClientError: An error occurred (ValidationException) when calling the Query operation: Invalid KeyConditionExpression: Incorrect operand type for operator or function; operator or function: >, operand type: M

据我了解,类型 M 将是映射或字典类型,而我使用的类型 N 是数字类型,并且与我的范围键的表方案相匹配。如果有人可以解释为什么会发生此错误,或者即使您无法解释为什么会出现此错误,我也愿意以不同的方式完成相同的查询。

【问题讨论】:

  • 你发现你的代码有什么问题了吗?我遇到了类似的问题。

标签: amazon-dynamodb boto3


【解决方案1】:

当您使用从boto3.dynamodb.conditions 导入的 Key 和 Attr 函数时,Boto 3 SDK 会为您构造一个条件表达式:

response = table.query(
    KeyConditionExpression=Key('hash_key').eq(hash_value) & Key('range_key').eq(range_key_value)

)

参考:Step 4: Query and Scan the Data

希望对你有帮助

【讨论】:

  • 跟进有关此问题的问题,但您知道是否有办法批量执行此操作吗?
  • 我有一个哈希值列表。有什么方法可以使用列表理解加入带有布尔值| 的列表吗?类似于'|'.join([Key('hash_key').eq(v) for v in values])
  • @falsePockets 刚试了一下,提示“调用查询操作时发生错误(ValidationException):KeyConditionExpressions 每个键只能包含一个条件”
  • @falsePockets 你不能在 Dynamo Key 中搜索范围,你必须使用 FilterExpresion ``` python response = table.query( KeyConditionExpression=Key('hash_key').eq(hash_value) FilterConditionExpression=键('range_key').gr(range_key_value))```
【解决方案2】:

将此解决方案添加为接受的答案并不能解决使用的查询不起作用的原因。

TLDR:在 boto3 中对 Table 资源使用查询与使用 client.query(...) 相比存在细微差别,并且需要不同的语法。

该语法对客户端上的查询有效,但对表无效。表上的ExpressionAttributeValues 不需要您指定数据类型。此外,如果您正在对 Table 资源执行查询,则不必再次指定 TableName。

工作解决方案:

from boto3.session import Session

dynamodb_session = Session(aws_access_key_id=AWS_KEY,aws_secret_access_key=AWS_PASS,region_name=DYNAMODB_REGION)

dynamodb = dynamodb_session.resource('dynamodb')
table = dynamodb.Table(TABLE_NAME)

request = {
    'ExpressionAttributeNames': {
        '#n0': 'hash_key',
        '#n1': 'range_key'
    },
    'ExpressionAttributeValues': {
        ':v0': MY_HASH_KEY,
        ':v1': GT_RANGE_KEY
    },
    'KeyConditionExpression': '(#n0 = :v0) AND (#n1 > :v1)',
}
response = table.query(**request)

我是一个名为botoful 的包的作者,它可能有助于避免处理这些复杂性。使用botoful的代码如下:

import boto3
from botoful import Query

client = boto3.Session(
    aws_access_key_id=AWS_KEY,
    aws_secret_access_key=AWS_PASS,
    region_name=DYNAMODB_REGION
).client('dynamodb')

results = (
    Query(TABLE_NAME)
        .key(hash_key=MY_HASH_KEY, range_key__gt=GT_RANGE_KEY)
        .execute(client)
)

print(results.items)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-28
    • 2017-07-18
    • 2020-08-06
    相关资源
    最近更新 更多