当前位置: 首页 > 知识库问答 >
问题:

使用散列键和Boto3的范围键查询DynamoDB

甘西岭
2023-03-14

我在使用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是数字类型,与我的范围键表方案相匹配。如果有人能解释为什么会发生这个错误,或者我也愿意用不同的方式完成相同的查询,即使你不能解释为什么会出现这个错误。

共有2个答案

阴波峻
2023-03-14

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

TLDR:在boto3中对资源使用查询与使用client.query(…)有细微的区别,需要不同的语法。

该语法对客户端上的查询有效,但对表无效。表上的表达式属性值不要求您指定数据类型。此外,如果要对资源执行查询,则无需再次指定表名

工作解决方案:

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)
王辉
2023-03-14

当您使用从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)

)

参考:步骤4:查询和扫描数据

希望能有帮助

 类似资料:
  • 创建TABLE TABLE(int键、time时间戳、度量浮点、主键(key、time)); 我需要创建一个火花作业,这将读取数据从上一个表,在指定的开始和结束时间戳做一些处理,并刷新结果回Cassandra。 因此,我的spark-cassandra-connector必须对集群cassandra表列进行范围查询。 范围查询的选择性约为1%,不可能在查询中包含分区键。 这两种解决方案哪一种更好?

  • 我必须经常在那里做两件事:1。给定一个category#域,获取所有匹配项。2.给定grouptype#groupname,获取所有匹配项。 这两种操作都相当频繁,所以我不想使用扫描。在DynamoDB中有没有一种有效的方法可以做到这一点?是否有更好的方法来设计模式(更多的表、辅助索引等)?任何建议都是有帮助的。有人建议使用全局辅助索引,但我的问题是,我能否将主表的范围键作为GSI的哈希键?我知道

  • 在文档中(http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/APISummary.html)它说: 只能查询主键为哈希和范围类型的表 和 我们建议您设计应用程序,以便主要使用查询操作,并仅在适当的情况下使用扫描 它没有直接声明,但这是否是使用散列和范围主键的最佳实践? 编辑: 回答TL;DR:使用对您的数据模型有意义的主

  • 是否可以使用哈希和 我想在查询中比较三个属性。两个是主哈希键和范围键,第三个是本地二级索引的范围键。

  • 问题内容: 如何在SQLite中高效地执行简单范围查询? 说,我有保存个人信息的数据,我想找到年龄在20到45岁之间,体重在50到80公斤之间的人? 我应该怎么做(例如设置某些索引?)以提高搜索效率? 问题答案: 我会尝试像 对“年龄”和“体重”字段建立索引将有助于加快查询速度。 这是有关在SQLite中建立索引的很好的概述:http : //www.tutorialspoint.com/sqli

  • 我有一个带有哈希键(id)的表(配置文件),我有一个关于名称的GSI,一个关于国家的范围键。我想创建一个DAO方法,它将获取所有具有给定值的name和country的记录,如下所示:List getProfileWithNameAndCountry(name,country);