查询条件错过了关键模式元素:验证错误

时间:2017-12-06 18:27:54

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

我正在尝试使用以下代码查询2017-12-06 19:18:13.891 WARN 11252 --- [uits-Executor-1] i.g.j.c.liquibase.AsyncSpringLiquibase : Starting Liquibase asynchronously, your database might not be ready at startup! 2017-12-06 19:18:34.044 DEBUG 11252 --- [ restartedMain] i.g.j.c.apidoc.SwaggerConfiguration : Starting Swagger 2017-12-06 19:18:34.055 DEBUG 11252 --- [ restartedMain] i.g.j.c.apidoc.SwaggerConfiguration : Started Swagger in 8 ms 2017-12-06 19:18:41.574 INFO 11252 --- [ restartedMain] com.akton.test.DemoApp : Started DemoApp in 51.121 seconds (JVM running for 51.852) 2017-12-06 19:18:46.161 DEBUG 11252 --- [uits-Executor-1] i.g.j.c.liquibase.AsyncSpringLiquibase : Liquibase has updated your database in 32269 ms 2017-12-06 19:18:46.161 WARN 11252 --- [uits-Executor-1] i.g.j.c.liquibase.AsyncSpringLiquibase : Warning, Liquibase took more than 5 seconds to start up!

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状态的所有作业。

5 个答案:

答案 0 :(得分:23)

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

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

答案 1 :(得分:2)

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

AWS dox on Querying a Table指出,您可以DynamoDB方式进行WHERE条件查询(例如SQL查询SELECT * FROM Music WHERE Artist ='Noone You Know';),但要注意一个重要警告:

“您必须为PARTITION键指定一个EQUALITY条件,并且可以选择为SORT键提供另一个条件。” (这意味着您只能将关键属性与Query一起使用。以其他任何方式进行操作都意味着DynamoDB会为您运行完整扫描,但效率不高-比使用全局二级索引效率低。)

因此,如果您需要使用Query来查询非关键属性,通常不是一个选择-最佳选择是使用Global Secondary Indexes,如@smcstewart所建议。

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

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

答案 2 :(得分:0)

我在其他情况下遇到此错误。这是我的情况。 (其他人以这种情况结束的可能性很小,但以防万一)

我在一个表上工作(例如表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();

'''

我创建了另一个表TableB。在命名键时发生了一些错误,因此我只是删除并再次创建了一个具有相同名称的表TableB。表B具有分区键m_id和排序键s_id。

我复制并粘贴了与表A相同的查询,只是因为分区键具有相同的名称,所以更改了表名。

令我震惊的是,我得到了这种期望。

“ ValidationException:查询条件缺少键架构元素”

我重新检查了所有名称,将查询与工作查询进行了比较。一切都很好。 我想也许是因为,我正在删除重新创建表B,可能与此有关。因此,我用新名称表B2创建了一个新表,该表具有与表B相同的键名。

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

如果您是在一个新的表上获得此表(以前没有查询曾在其中工作过),则可以选择使用新名称创建一个新表。

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

答案 3 :(得分:0)

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

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

注意:扫描操作的成本确实很高,尤其是当你的表很大时

答案 4 :(得分:-1)

我使用带扫描的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);

        }
    }