76

I am trying to query dynamodb using the following code:

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);
});

When I run this, I get an error saying:

ValidationException: Query condition missed key schema element: id

I do not understand this. I have defined id as the partition key for the jobs table and need to find all the jobs that are in processing status.

Suhail Gupta
  • 22,386
  • 64
  • 200
  • 328

5 Answers5

82

You're trying to run a query using a condition that does not include the primary key. This is how queries work in DynamoDB. You would need to do a scan for the info in your case, however, I don't think that is the best option.

I think you want to set up a global secondary index and use that to query for the processing status.

smcstewart
  • 2,016
  • 14
  • 16
  • 9
    Could you please discuss this here at https://chat.stackoverflow.com/rooms/160644/migrated-from-https-stackoverflow-com-questions-47681108-query-condition-missed – Suhail Gupta Dec 06 '17 at 19:20
  • 3
    Isn't a query vs a key lookup by definition already targeting a GSI? I'm reaching this error while running a query operation on a GSI... – fIwJlxSzApHEZIl Sep 16 '18 at 23:04
  • @anon58192932 Without knowing specifics, my gut tells me the field you're trying to filter on is not in your GSI. If you've got specifics, even better. – smcstewart Sep 18 '18 at 10:02
  • There are a couple ways to reach this error. Two that I found were: 1) using the deprecated api in lieu of KeyConditionExpression and 2) a typo in my GSI definition. there was a mismatch between the value I wanted the GSI to be an index on and what the index actually was on. Deleting and re-defining the index fixed it. – fIwJlxSzApHEZIl Sep 18 '18 at 19:17
27

In another answer @smcstewart responded to this question. But he provides a link instead of commenting why this error occurs. I want to add a brief comment hoping it will save your time.

AWS docs on Querying a Table states that you can do WHERE condition queries (e.g. SQL query SELECT * FROM Music WHERE Artist='No One You Know') in the DynamoDB way, but with one important caveat:

You MUST specify an EQUALITY condition for the PARTITION key, and you can optionally provide another condition for the SORT key.

Meaning you can only use key attributes with Query. Doing it in any other way would mean that DynamoDB would run a full scan for you which is NOT efficient - less efficient than using Global secondary indexes.

So if you need to query on non-key attributes using Query is usually NOT an option - best option is using Global Secondary Indexes as suggested by @smcstewart.

I found this guide to be useful to create a Global secondary index manually.

If you need to add it using CloudFormation here is a relevant page.

Paul T. Rawkeen
  • 3,994
  • 3
  • 35
  • 51
Ula
  • 2,628
  • 2
  • 24
  • 33
1

I was getting this error for a different scenario. Here is my scenario. (It's very unlikely that anyone else ends up with this case, but incase)

I had a query working on a Table (say table A). Table A had a partition key m_id and sort key u_id. I had a query to fetch data using m_id. The query was working.

'''

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

'''

I created another Table say Table B. I made some errors in naming keys so I simply deleted and created a table with the same name again, Table B. Table B had partition key m_id, and sort key s_id.

I copied pasted the same query which I was using for Table A, I changed Table name only because partition key had the same name.

To my shock, I get this expectation.

"ValidationException: Query condition missed key schema element"

I rechecked all the names, I compared the query with the working query. Everything was fine. I thought maybe because, I was deleting recreating Table B, it could be something with that. So I create a fresh Table with a new Name Table B2 with the same key names as Table B.

In my query that was throwing exceptions, I changed only the Table name from B to B2. And the Exception was gone.

If you are getting this on a fresh table, where no query has worked earlier, creating a new Table with a new name is an option.

If you delete a Table only to change partition key names, it may be safer to use a new name for Table as well (Dynamo could be referring metadata by table names and not by internal identifiers, it is possible that old metadata stays even if you delete a table. Just a guess given I faced this case).


EDIT:2022-July-12

This error does not leave me. My own answer was helpful but one more case, there was a trailing space in name of Key in the table. And Dynamo does not even check for spaces in key names.

Sandeep Dixit
  • 799
  • 7
  • 12
0

You have to create an global secondary index for the status field. Then, you code could look like smth like this:

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

Note: scan operation is indeed very costly, especially if you table is huge in size

Vitalii
  • 11
-1

i solved the problem using AWS.DynamoDB.DocumentClient() with scan, for sample (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);

        }
    }
dfloresdev
  • 76
  • 8