轻松从DynamoDB查询中获取所有结果!
#node #dynamodb

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,而更有效的方法是使用异步生成器。