You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在DynamoDB中基于排序键而非分区键查询数据?

解决DynamoDB仅用排序键查询的报错问题

嘿,这个报错我太熟悉了——这是DynamoDB的核心规则在起作用:Query操作必须指定分区键(也就是你的表中的ID。因为Query是基于主键(分区键+排序键)的定向查询,排序键只能作为分区键的补充来做范围过滤,单独拿排序键当查询条件是不被允许的,这就是你看到Query condition missed key schema element: ID的根本原因。

针对你要检索所有Updated大于"2018-02-01"记录的需求,我给你两种靠谱的解决方案,拆解得明明白白:

方案一:创建全局二级索引(GSI)【推荐生产环境使用】

这是最贴合DynamoDB设计理念的做法。你可以给表创建一个以Updated为分区键的全局二级索引,这样就能通过Query这个索引直接筛选时间范围的记录了。

操作步骤&示例代码(以boto3为例)

  1. 给表添加GSI:
import boto3
from boto3.dynamodb.conditions import Key

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('你的表名')

# 更新表结构,添加以Updated为分区键的GSI
table.update(
    AttributeDefinitions=[
        {
            'AttributeName': 'Updated',
            'AttributeType': 'S'  # 匹配你表中Updated的字符串类型日期
        }
    ],
    GlobalSecondaryIndexUpdates=[
        {
            'Create': {
                'IndexName': 'Updated-index',
                'KeySchema': [
                    {
                        'AttributeName': 'Updated',
                        'KeyType': 'HASH'
                    }
                ],
                'Projection': {
                    'ProjectionType': 'ALL'  # 可按需选择只投影需要的字段,降低存储成本
                },
                'ProvisionedThroughput': {
                    'ReadCapacityUnits': 5,
                    'WriteCapacityUnits': 5
                }
            }
        }
    ]
)
  1. 通过GSI执行Query查询:
response = table.query(
    IndexName='Updated-index',
    KeyConditionExpression=Key('Updated').gt('2018-02-01')
)
items = response['Items']
# 按需处理查询结果

方案二:使用Scan操作【仅临时/小数据量场景使用】

如果只是临时查询或者表的数据量极小,可以用Scan来全表过滤,但必须提醒你:Scan会遍历表中所有数据,数据量大时不仅速度慢,还会消耗更多读写容量,成本很高,绝对不推荐在生产环境的大数据量表上使用。

示例代码

from boto3.dynamodb.conditions import Attr

response = table.scan(
    FilterExpression=Attr('Updated').gt('2018-02-01')
)
items = response['Items']
# 数据量大时需处理分页
while 'LastEvaluatedKey' in response:
    response = table.scan(
        FilterExpression=Attr('Updated').gt('2018-02-01'),
        ExclusiveStartKey=response['LastEvaluatedKey']
    )
    items.extend(response['Items'])

额外小提示

如果你的需求是针对某个特定ID,查询它的Updated大于某个值,那直接用原始表的Query就行,比如:

response = table.query(
    KeyConditionExpression=Key('ID').eq('1201') & Key('Updated').gt('2018-02-01')
)

内容的提问来源于stack exchange,提问作者Octopus

火山引擎 最新活动