查询条件缺少关键架构元素:验证错误

Posted

技术标签:

【中文标题】查询条件缺少关键架构元素:验证错误【英文标题】:Query condition missed key schema element : Validation Error 【发布时间】:2018-05-20 17:40:59 【问题描述】:

我正在尝试使用以下代码查询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 状态的作业。

【问题讨论】:

【参考方案1】:

您正在尝试使用不包含主键的条件运行查询。这是how queries work in DynamoDB。您需要发送scan for the info in your case,但是,我认为这不是最好的选择。

我认为您想设置一个global secondary index 并使用它来查询processing 状态。

【讨论】:

请您在chat.***.com/rooms/160644/…这里讨论这个问题 根据定义,查询与键查找不是已经针对 GSI 了吗?我在 GSI 上运行查询操作时遇到此错误... @anon58192932 在不知道具体情况的情况下,我的直觉告诉我您要过滤的字段不在您的 GSI 中。如果您有具体细节,那就更好了。 有几种方法可以解决此错误。我发现的两个是:1)使用已弃用的 api 代替 KeyConditionExpression 和 2)我的 GSI 定义中的错字。我希望 GSI 作为索引的值与索引的实际值之间存在不匹配。删除并重新定义索引修复了它。 仅仅这个问题和答案就让我远离了这个数据库。【参考方案2】:

在另一个答案中 @smcstewart 回答了这个问题。但是他提供了一个链接,而不是评论为什么会发生这个错误。我想添加一个简短的评论,希望它能节省您的时间。

AWS docs on Querying a Table 表示您可以使用 DynamoDB 方式进行WHERE 条件查询(例如SQL query SELECT * FROM Music WHERE Artist='No One You Know'),但有一个重要警告:

您必须为 PARTITION 键指定一个 EQUALITY 条件,并且您可以选择为 SORT 键提供另一个条件。

意思是你只能使用Query的关键属性。以任何其他方式执行此操作将意味着 DynamoDB 将为您运行 完全扫描,这效率不高 - 效率低于使用全局二级索引。

因此,如果您需要使用 Query 查询非关键属性,通常不是一种选择 - 最好的选择是按照 @smcstewart 的建议使用 Global Secondary Indexes。

我发现this guide 对手动创建全局二级索引很有用。

如果您需要使用 CloudFormation here is a relevant page 添加它。

【讨论】:

【参考方案3】:

我使用 AWS.DynamoDB.DocumentClient() 扫描解决了这个问题,用于示例(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);

        
    

【讨论】:

这不是一个可取的解决方案。扫描操作非常昂贵! 是的,重建你的表,添加一些索引并进行查询【参考方案4】:

我在不同的情况下收到此错误。这是我的场景。 (其他人不太可能以这种情况告终,但以防万一)

我有一个查询表(比如表 A)。表 A 有一个分区键 m_id 和排序键 u_id。 我有一个使用 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,这可能与此有关。因此,我创建了一个新表,其名称表 B2 与表 B 具有相同的键名。

在引发异常的查询中,我仅将表名称从 B 更改为 B2。 异常消失了。

如果您在新表上获取此信息,而之前没有任何查询有效,则可以选择创建一个具有新名称的新表。

如果您删除表只是为了更改分区键名称,那么为表使用新名称可能会更安全(Dynamo 可以通过表名而不是内部标识符来引用元数据,即使您删除了一个表,旧的元数据也可能会保留下来。鉴于我遇到了这种情况,这只是一个猜测)。

【讨论】:

【参考方案5】:

您必须为状态字段创建一个全局二级索引。 然后,您的代码可能看起来像这样:

dynamo.query(
  TableName: "Jobs",
  IndexName: 'status',
  KeyConditionExpression: '#s = :st',
  ExpressionAttributeValues: 
    ':st': 'processing'
  ,
  ExpressionAttributeNames: 
      '#s': 'status',
    ,
, (err, resp) => 
  console.log(err, resp);
);

注意:扫描操作确实非常昂贵,尤其是如果您的表很大时

【讨论】:

以上是关于查询条件缺少关键架构元素:验证错误的主要内容,如果未能解决你的问题,请参考以下文章

用于查询 dynamodb 的 boto3 资源:查询条件缺少关键架构元素

C# dynamodb 错误:查询条件缺少键架构元素:主键

Oracle SQL - 使用 Case 语句缺少关键字错误的更新查询

当我尝试通过架构使用 DocumentBuilderFactory 验证 xml 文件时,我收到错误“找不到元素的声明”

无法将类型编组为元素,因为它缺少自动生成的类的@XmlRootElement注释

架构验证:表 [process_event] 中缺少列 [event_id]。不知道为啥