DynamoDb: 扫描查询未返回所有数据

17

我有一个包含数千条数据的DynamoDb表。我使用Scan函数扫描该表,并应用了“Between”FilterExpression。然而,查询响应仅返回3条记录,而应该返回约100条记录。

我使用Node js创建了Lambda函数。


1
最有可能的原因是过滤表达式正在过滤掉一些值。在这种情况下,DynamoDB仍必须扫描整个表并浏览结果。每个响应将仅包括与过滤条件匹配的项目和一个LastEvaluateKey,您必须在下一个请求中包含它以继续扫描。这一点起初可能有点不直观,但如果您再多想一会儿就会明白其中的道理。 - Mike Dinescu
使用Node.jsAWS Dynamodb获取/扫描所有项,您可以参考以下链接:https://dev59.com/CVcP5IYBdhLWcg3wTYYn - Yuci
3个回答

17

另一个常见问题可能是扫描是否执行到LastEvaluatedKey为空。

如果您已经这样做了,但仍然没有获取到所有的项,请展示您的代码以便详细查看。

如果扫描的总项数超过1 MB的最大数据集大小限制,则扫描将停止并将结果作为LastEvaluatedKey值返回给用户,以便在随后的操作中继续扫描。结果还包括超过限制数量的项目数。扫描可能导致没有满足筛选条件的表数据。

如果LastEvaluatedKey为空,则表示已处理完结果的“最后一页”,没有更多数据可供检索。

如果LastEvaluatedKey不为空,这并不一定意味着结果集中还有更多数据。唯一确定已经到达结果集末尾的方法是LastEvaluatedKey为空时。


12

这是一个获取所有结果的示例代码:

 Map<String, AttributeValue> lastKeyEvaluated = null;
    do {
        ScanRequest sr = new ScanRequest()
                .withTableName("tableName")
                .withProjectionExpression("id")
                .withExclusiveStartKey(lastKeyEvaluated);
        ScanResult result = client.scan(sr);
        for (Map<String, AttributeValue> item : result.getItems()) {
            System.out.println(item.get("id").getS());
        }
        lastKeyEvaluated = result.getLastEvaluatedKey();
    } while (lastKeyEvaluated != null);

3
请在您的回答中添加一些描述。 - not2qubit
这个答案帮了很多,谢谢。然而请注意,使用 AWS SDK 2.0 时,result.getLastEvaluatedKey() 返回一个空的、而不是 null 的 map。因此,我只需要将 while 条件更改为检查 != null && !empty 即可。 - dewald

0

使用 Node.js,我正在使用查询从数据库检索项目。一个单独的查询操作最多可以检索 1 MB 的数据。这就是为什么我创建了一个递归函数来从数据库检索并连接数据,直到我们从响应中接收到 LastEvaluatedKey 为止。 当我们收到值为 nullLastEvaluatedKey 时,表示没有更多数据了。 我的函数使用索引从数据库中获取数据。使用查询功能将比扫描更快、更有效。

实际上,getItemByGSI 函数具有许多用于查询过滤和自定义的参数,这可能会很有用。当然,您可以删除对用例不必要的参数。

因此,getAllItemsByGSI 函数可用于检索 DynamoDB 中的所有数据,而 getItemByGSI 可用于使用单个查询。

'use strict';
    
    const omitBy = require('lodash/omitBy');
    const isNil = require('lodash/isNil');
    const AWS = require('aws-sdk');
    
    const call = (action, params) => {
        return new Promise((resolve, reject) => {
            try {
                const dynamoDb = new AWS.DynamoDB.DocumentClient();
                resolve(dynamoDb[action](params).promise());
            } catch (error) {
                reject(error);
            }
        });
    };
    
    const getItemByGSI = ({
        TableName,
        IndexName,
        attribute,
        value,
        sortKey,
        sortValue,
        filter,
        filterValue,
        operator,
        filter1,
        filterValue1,
        LastEvaluatedKey,
        ScanIndexForward,
        Limit,
    }) => {
        return new Promise(async (resolve, reject) => {
            try {
                const params = {
                    TableName,
                    IndexName,
                    KeyConditionExpression: '#attrKey = :attrValue',
                    ExpressionAttributeValues: { ':attrValue': value },
                    ExpressionAttributeNames: { '#attrKey': attribute },
                    ExclusiveStartKey: LastEvaluatedKey,
                    Limit,
                    FilterExpression: null,
                };
                sortKey && sortValue
                    ? (params.KeyConditionExpression +=
                            ' and #sortKey = :sortValue' &&
                            (params.ExpressionAttributeNames['#sortKey'] = sortKey) &&
                            (params.ExpressionAttributeValues[':sortKey'] = sortValue))
                    : '';
                filter && filterValue
                    ? (params.FilterExpression = `#${filter} = :${filter}`) &&
                      (params.ExpressionAttributeNames[`#${filter}`] = filter) &&
                      (params.ExpressionAttributeValues[`:${filter}`] = filterValue)
                    : '';
                filter && filterValue && operator && filter1 && filterValue1
                    ? (params.FilterExpression += ` ${operator} #${filter1} = :${filter1}`) &&
                      (params.ExpressionAttributeNames[`#${filter1}`] = filter1) &&
                      (params.ExpressionAttributeValues[`:${filter1}`] = filterValue1)
                    : '';
                params = omitBy(params, isNil);
                if (ScanIndexForward === false)
                    params.ScanIndexForward = ScanIndexForward;
                const result = await call('query', params);
                resolve(result);
            } catch (error) {
                reject(error);
            }
        });
    };
    
    const getAllItemsByGSI = (data) => {
        return new Promise(async (resolve, reject) => {
            try {
                const finalData = [];
                const gettingData = await getItemByGSI(data);
                finalData = finalData.concat(gettingData.Items);
                if (gettingData.LastEvaluatedKey) {
                    const final2 = await getAllItemsByGSI({
                        ...data,
                        LastEvaluatedKey: gettingData.LastEvaluatedKey,
                    });
                    finalData = finalData.concat(final2);
                }
                resolve(finalData);
            } catch (err) {
                reject(err);
            }
        });
    };
    
    module.exports = {
        getItemByGSI,
        getAllItemsByGSI,
    };


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接