CLI命令 - 结果分页

在前面章节我们讲到Scan命令会扫描全表,并且返回最多1MB数据。ScanQuery类似,不同之后我们是扫描的全表,而不是一个Item Collection,另外在Scan中不能传入Key Condition表达式。但可以使用Filter表达式来减少返回结果的数量

例如,查询Reply表中所有User A发表的评价:

aws dynamodb scan \
    --table-name Reply \
    --filter-expression 'PostedBy = :user' \
    --expression-attribute-values '{
        ":user" : {"S": "User A"}
    }' \
    --return-consumed-capacity TOTAL

在返回结果里看到:

"Count": 3,
"ScannedCount": 4,

这表明Scan扫描了全表的4条记录,但是Filter表达式筛选出来3条满足条件的

分页返回结果

有时候Scan返回的结果条目非常多,如果想对它分页的话,可以使用--max-items来指定返回结果的数量,使用NextToken来查询后面的结果。例如上面的查询返回了3条结果,我们将最大结果数量设置为2,这样总共有两页数据,第一次查询:

aws dynamodb scan \
    --table-name Reply \
    --filter-expression 'PostedBy = :user' \
    --expression-attribute-values '{
        ":user" : {"S": "User A"}
    }' \
    --max-items 2 \
    --return-consumed-capacity TOTAL

我们看到在返回结果里有个NextToken字段:

image-20230107230333411

所以可以再次调用scan,在starting-token参数传入NextToken

aws dynamodb scan \
    --table-name Reply \
    --filter-expression 'PostedBy = :user' \
    --expression-attribute-values '{
        ":user" : {"S": "User A"}
    }' \
    --max-items 2 \
    --starting-token eyJFeGNsdXNpdmVTdGFydEtleSI6IG51bGwsICJib3RvX3RydW5jYXRlX2Ftb3VudCI6IDJ9 \
    --return-consumed-capacity TOTAL

使用LastEvaluatedKey

如果有LastEvaluatedKey,则进行后面的遍历;如果LastEvaluatedKey为空,则所有数据已全部取回。

例如:

import boto3
import json
import time

dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table("employees")

response = table.scan(Limit=100)
data = response['Items']
queryCount=1
for item in data:
    print(item['PK'])
print("---------------------", queryCount,time.time())

while 'LastEvaluatedKey' in response:
    print(response['LastEvaluatedKey'])
    queryCount += 1
    response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey'],Limit=100)
    data = (response['Items'])

    for item in data:
        print(item['PK'])
    print("--------------------------",queryCount,time.time())

image-20241226204409990

每次scan是否要扫全表?答案是否,因为每次传入了LastEvaluatedKey,这个Key其实是PK+SK,有了这两个字段,就可以迅速定位到起始位置。

例如当Limit=10时,扫描一个很大的表,每次返回结果都在几十毫秒,这说明不是全表扫描。