查询条件缺少关键模式元素:验证错误。

77

我正在尝试使用以下代码查询dynamodb:

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

let dynamo = new AWS.DynamoDB.DocumentClient({
  service: new AWS.DynamoDB(
    {
      apiVersion: "2012-08-10",
      region: "us-east-1"
    }),
  convertEmptyValues: true
});

dynamo.query({
  TableName: "Jobs",
  KeyConditionExpression: 'sstatus = :st',
  ExpressionAttributeValues: {
    ':st': 'processing'
  }
}, (err, resp) => {
  console.log(err, resp);
});

当我运行这个程序时,出现了一个错误:

ValidationException: Query condition missed key schema element: id

我不理解这个。我已经将id定义为jobs表的分区键,并需要找到所有处于processing状态的工作。

5个回答

82

9
请问您能否在 https://chat.stackoverflow.com/rooms/160644/migrated-from-https-stackoverflow-com-questions-47681108-query-condition-missed 这里讨论一下? - Suhail Gupta
3
按照定义,查询和键查找不是已经针对GSI进行了吗?我在对一个GSI运行查询操作时遇到了这个错误... - fIwJlxSzApHEZIl
@anon58192932 没有具体细节的情况下,我的直觉告诉我你试图过滤的字段不在你的GSI中。如果你有具体细节,那就更好了。 - smcstewart
有几种方法可以导致这个错误。我发现的两种是:1)使用已弃用的API代替KeyConditionExpression;2)在我的GSI定义中出现了拼写错误。我想要GSI作为索引的值与实际上的索引不匹配。删除并重新定义索引即可解决问题。 - fIwJlxSzApHEZIl

27
在另一个回答中,@smcstewart 回答了这个问题。但他提供了一个链接而不是解释为什么会出现这个错误。我想添加一个简短的评论,希望能节省您的时间。 AWS文档上关于查询表格的内容 表示你可以使用 DynamoDB 的方式进行 WHERE 条件查询(例如:SQL 查询 SELECT * FROM Music WHERE Artist='No One You Know'),但有一个重要的限制:

必须为 PARTITION key 指定一个 EQUALITY condition,并且可以可选地提供一个 SORT key 的条件。

意思是你只能使用关键属性来进行查询。以任何其他方式进行查询将意味着 DynamoDB 将为您运行一个完全扫描,这是不高效的——比使用全局二级索引不高效。
因此,如果您需要在非关键属性上进行查询,则通常不适合使用 Query——最好的选择是使用@smcstewart建议的全局二级索引
我发现 这个指南 对于手动创建全局二级索引很有用。

如果你需要使用CloudFormation添加它,这里有一个相关页面


1

我之前遇到过一个不同的问题,出现了这个错误。以下是我的情况。 (很少有人会遇到这种情况,但以防万一)

我对一个带有分区键m_id和排序键u_id的表(称为表A)上的查询进行了操作。我编写了一条使用m_id获取数据的查询语句。这条查询语句正常工作。

'''

var queryParams = {
        ExpressionAttributeValues: {
          ':m_id': mId
         },
       KeyConditionExpression: 'm_id = :m_id',
       TableName: "A"
      };
    
   let connections = await docClient.query(queryParams).promise();

'''

我创建了另一个表,称为表B。由于命名键时出现了一些错误,所以我只是删除了表并再次创建了一个同名的表B。表B具有分区键m_id和排序键s_id。
我复制粘贴了与表A相同的查询,只更改了表名,因为分区键名称相同。
令我震惊的是,我得到了这个期望。
"ValidationException:查询条件缺少关键架构元素"
我重新检查了所有名称,将查询与工作查询进行了比较。一切都很好。 我认为可能是因为我正在删除重新创建表B,所以可能与此有关。因此,我创建了一个新名称为Table B2的全新表,其键名与表B相同。
在引发异常的查询中,我仅将表名从B更改为B2。 然后异常消失了。
如果您在全新的表上遇到此问题,其中没有任何查询起作用,请创建一个具有“新名称”的新表是一个选项。
如果您仅删除表以更改分区键名称,则最好为表使用新名称(Dynamo可能会按表名称而不是内部标识符引用元数据,因此即使您删除表,旧元数据也可能存在。只是一个猜测,因为我曾经遇到过这种情况)。

编辑:2022年7月12日

这个错误一直困扰着我。我的回答很有帮助,但还有一个情况,表中键名末尾有一个空格。而且 Dynamo 甚至不会检查键名中的空格。


0
你需要为状态字段创建一个全局二级索引。 然后,你的代码可能看起来像这样:
dynamo.query({
  TableName: "Jobs",
  IndexName: 'status',
  KeyConditionExpression: '#s = :st',
  ExpressionAttributeValues: {
    ':st': 'processing'
  },
  ExpressionAttributeNames: {
      '#s': 'status',
    },
}, (err, resp) => {
  console.log(err, resp);
});

注意:扫描操作确实非常昂贵,特别是如果您的表非常大。

-1

我使用 AWS.DynamoDB.DocumentClient() 与 scan 方法解决了这个编程问题,以下为示例(使用 nodejs):

var docClient = new AWS.DynamoDB.DocumentClient();
var params = {
        TableName: "product",
        FilterExpression: "#cg = :data",
        ExpressionAttributeNames: {
            "#cg": "categoria",
        },

        ExpressionAttributeValues: {
             ":data": category,
        }
    };

docClient.scan(params, onScan);

    function onScan(err, data) {
        if (err) {
            // for the log in server
            console.error("Unable to scan the table. Error JSON:", JSON.stringify(err, null, 2));
            res.json(err);
        } else {

            console.log("Scan succeeded.");
            res.json(data);

        }
    }

8
这不是一个可取的方案。扫描操作非常昂贵! - Krishna
重建你的表,添加一些索引并执行查询。 - sensei

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