DynamoDB查询可以only return 1MB of results。那么,如果查询大于此,如何获得查询的所有结果呢?有两种方法:简单的方式和酷的方式。
DynamoDB查询分页的工作方式
在开始获得疯狂的记录之前,让我们备份并谈论分页在DynamoDB中的工作方式。当查询的记录超过其返回的记录时,要么是因为您设置了Limit
属性,要么是1MB
的结果,dynamo将返回所有可以与属性LastEvaluatedKey
一起返回的记录。
只要在查询结果中设置了LastEvaluatedKey
属性,就意味着您仍然可以获得结果。如果要获得这些结果,请更新原始查询参数,以便将ExclusiveStartKey
设置为LastEvaluatedKey
并再次运行查询。
简单的方式
最明显的方法是:使用DO循环。使条件检查是否设置了ExclusiveStartKey
。如果设置了,那么您知道还有更多记录,您应该再次运行查询。
export const getAllResults = async <T>(
db: AWS.DynamoDB.DocumentClient,
query: AWS.DynamoDB.DocumentClient.QueryInput
): Promise<Array<T>> => {
const result = [] as Array<T>;
console.info(`Querying Dynamo`, query.ExpressionAttributeValues);
let queryResult: AWS.DynamoDB.DocumentClient.QueryOutput;
do {
queryResult = await db.query(query).promise();
console.info(`Query Result`, queryResult);
query.ExclusiveStartKey = queryResult?.LastEvaluatedKey;
queryResult.Items?.forEach(item => result.push(item as T));
} while (query.ExclusiveStartKey);
console.info(
`Found ${result.length} results for ${query.KeyConditionExpression}`,
inspect(query.ExpressionAttributeValues)
);
return result;
};
使用异步生成器
do-loop的问题是所有结果都将存储在内存中。如果您有很多记录,那可能是一个问题。这样做的更典型的方法是使用node.js async发电机。
异步生成器是一种特殊类型的迭代器,可让您在检索时yield
值。以下代码示例创建了DynamoDB异步生成器。
export async function* getAllResults<T>(
db: AWS.DynamoDB.DocumentClient,
query: AWS.DynamoDB.DocumentClient.QueryInput
) {
console.info(`Querying Dynamo`, query.ExpressionAttributeValues);
let queryResult: AWS.DynamoDB.DocumentClient.QueryOutput;
do {
queryResult = await db.query(query).promise();
console.info(`Query Result`, queryResult);
query.ExclusiveStartKey = queryResult?.LastEvaluatedKey;
if(queryResult.Items) {
yield* queryResult.Items;
}
} while (query.ExclusiveStartKey);
};
称呼它
现在创建了发电机,您可以使用以下尴尬语法调用它。
for await (const record of getAllResults(db, query)) {
console.info(record);
}
结论
得出结论,如果您具有返回超过1MB结果的DynamoDB查询,那么处理分页的简单方法是使用DO-LOOP,而更有效的方法是使用异步生成器。