如何使用KeyConditionExpression查询AWS DynamoDb?

时间:2019-05-09 03:49:34

标签: node.js amazon-web-services amazon-dynamodb

我有一个AWS DynamoDb表,
我有user_id作为索引或GSI(user_id-index ),
而且我也有product_type作为索引或GSI(prod_type-in​​dex )。

我正在尝试使用KeyConditionExpression查询DynamoDb表,
但是我得到了-

Validation Exception, with message:"Query key condition not supported" and statusCode: 400
ValidationException: Query key condition not supported\n at Request.extractError 

我在桌子上有以下项目结构-

{
  "id": "12345f9f-f08c-45ae-986a-f1b5ac712345",
  "user_id": 1234,
  "prod_type": "OTHER"
}

以下是我用于查询表的NodeJs代码-

let AWS = require('aws-sdk');

AWS.config.update({
    region: 'us-east-1'
});

let connection = new AWS.DynamoDB.DocumentClient();

let table = "some_table";

let params = {
    IndexName : "user_id-index",
    ExpressionAttributeValues: {
        ":v1": {
            N: 1234
        },
        ":v2": {
            S: "OTHER"
        }
    },
    ExpressionAttributeNames: {
        "#userId": "user_id",
        "#prodType": "prod_type"
    },
    TableName: table,
    KeyConditionExpression: "#userId = :v1 and #prodType = :v2"
};

connection.query(params, function(err, data) {
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }
});

参考-
Dynamodb query error - Query key condition not supported
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.KeyConditions.html

3 个答案:

答案 0 :(得分:1)

根据文档here,问题是您的 ExpressionAttributeValues 值不正确。您需要提供变量和数据类型与值的映射。您需要像这样提供映射:

let params = {
   IndexName : "user_id-index",
   ExpressionAttributeValues: {
      ":v1": {
           N: 1234
       },
       ":v2": {
           S: "OTHER"
       }
   },
   TableName: table,
   KeyConditionExpression: "user_id = :v1 and prod_type = :v2"
};

您需要根据文档指定数据类型。 S 用于字符串文字, N 用于数字,等等。您可以在上面的文档中找到详细信息。我也强烈建议您也使用 ExpressionAttributeNames 。我发现它的效果更好,并且是此SDK的最佳做法。您需要像这样在 KeyConditionExpression 中替换在映射中指定的变量:

let params = {
   IndexName : "user_id-index",
   ExpressionAttributeValues: {
       ":v1": {
           N: 1234
       },
       ":v2": {
           S: "OTHER"
       }
   },
   ExpressionAttributeNames: {
       "#userId": "user_id",
       "#prodType": "prod_type"
   }
   TableName: table,
   KeyConditionExpression: "#userId = :v1 and #prodType = :v2"
};

参考-
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LegacyConditionalParameters.KeyConditions.html

答案 1 :(得分:1)

我在上一个答案中提到过。您不能将一个GSI /主键的哈希键和另一GSI /主键的哈希键放在单个 KeyConditionExpression

  

条件必须对单个分区键执行相等性测试   值。

     

该条件可以选择执行几种比较测试之一   在单个排序键值上。这允许查询检索一项   具有给定的分区键值和排序键值,或多个项目   具有相同的分区键值但具有不同的排序键值。

from the docs

DynamoDB不支持它,实际上是为了省钱。 您可以在此处执行的操作是使用更具体的GSI哈希键作为KeyConditionExpression,然后可以对结果集执行FilterExpression

否则,请设置一个GSI,该GSI的一个属性为哈希键,另一个属性为范围键。这样,您可以使用语法进行查询

partitionKeyName = :partitionkeyval AND sortKeyName = :sortkeyval

请记住,partitionKeyName仅支持相等性。 sortKeyName支持多种不同的操作

答案 2 :(得分:0)

有两种与dynamoDb进行交互的方式,您可以使用:AWS.DynamoDB(执行一些自定义类型包装,例如将数字包装为字符串)或AWS.DynamoDB.DocumentClient来为您进行类型包装-后者在大多数情况下更易于使用。

您正在调用DocumentClient,但是包装类型就像直接调用AWS.DynamoDB一样,将会失败

只需使用您的user_id索引(我假设它只是一个排序键,也不需要范围键),这应该可以工作:

  let params = {
     TableName: table,
     IndexName : "user_id-index",
     KeyConditionExpression: "user_id = :userId",
     ExpressionAttributeValues: { “:userId”: 1234 }
  }