当前位置: 首页 > 知识库问答 >
问题:

如何使用复合条件查询DynamoDB GSI

洪雅健
2023-03-14

我有一个名为“弗兰克”的DynamoDB表,只有一个GSI。分区键称为PK,排序键称为SK,GSI分区键称为GSI1_PKGSI排序键称为GSI1_SK。我有一个存储实际数据的“数据”映射。

GSI分区键和排序键直接映射到表中具有相同名称的属性。

我可以运行partiql查询来获取图像中显示的结果。以下是PartIQ代码:

select PK, SK, GSI1_PK, GSI1_SK, data from "frank"."GSI1"
where 
("GSI1_PK"='tesla')
and 
(
 (  "GSI1_SK" >= 'A_VISITOR#2021-06-01-00-00-00-000' and  "GSI1_SK" <= 'A_VISITOR#2021-06-20-23-59-59-999' )
 or
 (  "GSI1_SK" >= 'B_INTERACTION#2021-06-01-00-00-00-000'  and   "GSI1_SK" <= 'B_INTERACTION#2021-06-20-23-59-59-999' )
)

注意分区代码是如何多次引用“GSI1_SK”的。分区查询有效,并返回图像中显示的数据。到目前为止一切都很好。

但是,我现在想将其移动到Lambda函数中。如何构建AWS。发电机B。DocumentClient查询是否完全执行此partiql查询的操作?

我可以在Lambda函数中使用此函数:

const visitorStart="A_VISITOR#2021-06-01-00-00-00-000";
        const visitorEnd="A_VISITOR#2021-06-20-23-59-59-999";
        
        var params = {
          TableName: "frank",
          IndexName: "GSI1",
          KeyConditionExpression: "#GSI1_PK=:tmn AND #GSI1_SK BETWEEN :visitorStart AND :visitorEnd",
          ExpressionAttributeNames :{  "#GSI1_PK":"GSI1_PK", "#GSI1_SK":"GSI1_SK" },
          ExpressionAttributeValues: {
            ":tmn": lowerCaseTeamName,
            ":visitorStart": visitorStart,
            ":visitorEnd": visitorEnd
          }
        };
        
        const data = await documentClient.query(params).promise();
        console.log(data); 

但当我尝试一个更复杂的复合条件时,我得到了这个错误:

ValidationException: Invalid operator used in KeyConditionExpression: OR

下面是更复杂的尝试:

const visitorStart="A_VISITOR#2021-06-01-00-00-00-000";
        const visitorEnd="A_VISITOR#2021-06-20-23-59-59-999";
        const interactionStart="B_INTERACTION#2021-06-01-00-00-00-000";
        const interactionEnd="B_INTERACTION#2021-06-20-23-59-59-999";
        
        var params = {
          TableName: "frank",
          IndexName: "GSI1",
          KeyConditionExpression: "#GSI1_PK=:tmn AND (#GSI1_SK BETWEEN :visitorStart AND :visitorEnd OR #GSI1_SK BETWEEN :interactionStart AND :interactionEnd) ",
          ExpressionAttributeNames :{  "#GSI1_PK":"GSI1_PK", "#GSI1_SK":"GSI1_SK" },
          ExpressionAttributeValues: {
            ":tmn": lowerCaseTeamName,
            ":visitorStart": visitorStart,
            ":visitorEnd": visitorEnd,
            ":interactionStart": interactionStart,
            ":interactionEnd": interactionEnd
          }
        };
        
        const data = await documentClient.query(params).promise();
        console.log(data);  

文档说Key条件表达式不支持“OR”。那么,如何使用AWS. DynamoDB. DocumentClient在Lambda中复制更复杂的分区查询?

共有2个答案

曹高轩
2023-03-14

遗憾的是,DynamoDB不支持KeyConditionExpression中的多个布尔运算。您正在执行的partiql查询可能正在执行全表扫描以返回结果。

如果要使用DocumentClient复制partiql查询,可以使用扫描操作。如果要避免使用扫描,可以执行两个单独的查询操作,并将结果加入到应用程序代码中。

段干茂实
2023-03-14

如果您查看DynamoDB的PartiQL的留档,他们会警告您,PartiQL毫无顾忌地使用全表扫描来获取您的数据:https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.select.html#ql-reference.select.syntax

为了确保SELECT语句不会导致全表扫描,WHERE子句条件必须指定分区键。使用equality或IN运算符。

在这些情况下,PartiQL将运行扫描并使用FilterExpression来过滤数据

当然,在您的示例中,您提供了一个分区键,因此我假设分区QL将使用分区键和FilterExpress运行查询以应用其余条件。

您可以这样复制它,根据分区的大小,这可能会很好。但是,如果分区将超过1MB并且大部分数据将被过滤掉,即使您不会获得任何数据,您也需要处理分页。

因此,我建议您只需将其拆分,并将每个or条件作为单独的查询运行,然后合并客户端上的数据。

 类似资料:
  • 问题内容: 我有一个用于Elasticsearch的简单JSON查询,如下所示: 仅当值(在这种情况下为“ a1”)不为空时,才如何执行第二个“必须”条件? 问题答案: 您可以使用以下方法实现它-

  • 问题内容: SELECT supplier_id FROM suppliers UNION ALL 我只是在查询的“ UNION ALL”子句上方和查询的“ UNION ALL”子句上方创建两个条件。 但是我的问题是我如何在条件中执行UNION ALL子句?提前致谢。 问题答案: 我认为hibernate不支持条件,但是您可以使用两个条件查询来获得预期的结果:

  • 我有两个独立的索引- 1。产品 2。currency_rates 产品索引中的文档具有以下详细信息- currency_rates索引中的文档具有以下详细信息- 我希望在products index的price字段中实现排序, 但是由于product index中的每个文档可能有不同的货币, 我需要首先将所有货币转换为美元, 并在转换后的ResultSet上进行carryout排序。 以下是我的创

  • 问题内容: 我已经在hbm文件中添加了复合文件,如下所示 现在我想查询如下 我没有得到相同的结果,因为有一个引用EmployeeSignId的组合键。在这种情况下,如何创建条件查询? 我在下面尝试过但得到0条记录 问题答案: 问题已解决。 我尝试了下面的工作

  • 现在我需要正在学习‘程序设计’课程的学生名单 如何使用条件查询实现这一点。