Reputation:
Is there a way to get an item depending on a field that is not the hashkey?
Example
My Table Users: id (HashKey), name, email
And I want to retrieve the user having email as '[email protected]'
How this can be done?
I try this with boto:
user = users.get_item(email='[email protected]')
I get the following error:
'The provided key element does not match the schema'
Upvotes: 70
Views: 184576
Reputation: 461
I got the error, When the value of keyAttribute was null. Please check to see what data you are trying to store in the table.
Upvotes: 0
Reputation: 8497
When you create a table, There is a field for 'partition key' and a field for 'sort key (optional)'. If you enter something in the 'sort key' field, later you will need to use it in your calls by primary key such as get_item.
For example if my partition key is 'name' and my sort key is 'surname', I need to call it like this:
var params = {
TableName: 'mytable',
Key: {
'name': {S: 'John'},
'surname': {S: 'Sena'}
}
};
If you make a get_item call to this table only with the first part of the primary key (name), you get the 'The provided key element does not match the schema.' error because its missing the surname.
To fix it, add the sort key in your call (or recreate the table without a sort key).
Upvotes: 8
Reputation: 21
If you're using Java SDK - consider if your schema contains a @DynamoDbSortKey
within your Model class. If so, in order to satisfy the getItem
method and match your schema, you must provide both Partition Key and Sort Key to the method.
Key key = Key.builder()
.partitionValue(PK)
.sortValue(SK)
.build();
...
Entity entity = entityTable.getItem(item -> item.key(key));
Further, to convert any custom attributes, you should process key conversions to it's attribute value. Take the example of a java.util.Date
Object
// Provide AttributeConverter and convert the custom Attribute
AttributeConverter<Date> attributeConverter = new DateConverter();
AttributeValue SK = attributeConverter.transformFrom(Entity.getCreatedAt());
Upvotes: 1
Reputation: 19893
The exception The provided key element does not match the schema
happens when you define either a key or a value which does not conform to the schema for your table.
The original question wanted to obtain items based on a non-key attribute, and this got an exception as the partition key name did not align.
To overcome this issue, you would need to create a Global Secondary Index on the non-key attribute. As items in a GSI are not required to be unique, you lose the ability to use the GetItem
API, instead you must use the Query
API which will allow you to retrieve multiple items that match a key if they exist.
The current top rated answer is not in line with the question, but produces the same The provided key element does not match the schema
exception is caused by the differences in the high and low level client. High level clients take JSON values, and low level clients take DynamoDB-JSON. Mixing the parameters will cause exceptions. The differences are outlined in the following blog post:
https://aws.amazon.com/blogs/database/exploring-amazon-dynamodb-sdk-clients/
Upvotes: 2
Reputation: 1268
I received this error when using a field from the result of a DynamoDB get
call directly as the key to another get
call. The issue was that I didn't use .Item
so when the code dynamoResult.fieldName
was used as the key it would evaluate to undefined
, not the value I needed. This explains the error as undefined
is not a string (which is the type the HASH
key was set to).
To resolve this I changed dynamoResult.fieldName
to dynamoResult.Item.fieldName
Upvotes: 0
Reputation: 816
In case it helps anyone else just starting out with DynamoDB, I got this error when trying to use GetItemCommand
and only providing a Partition key on a table with a composite Primary key.
Either additionally specify a value for the Sort key to retrieve the single record that matches that combination, or switch to QueryCommand
to return anything matching just the partition key regardless of the Sort key.
Upvotes: 1
Reputation: 3535
I got this error in my AWS Lambda function, because my parameters was BigInt and needed to be converted to Number. I changed this:
let data = await docClient.get({ TableName: "items", Key: { "accountid": accountId, "itemid": itemId } }).promise();
... to this:
let data = await docClient.get({ TableName: "items", Key: { "accountid": Number(accountId), "itemid": Number(itemId) } }).promise();
Upvotes: 1
Reputation: 57297
I have a partition key and a sort key on my table.
I was querying it with only the partition key, and I got this error.
Obviously, querying the composite key fixed it.
Upvotes: 18
Reputation: 71
I got this error in my Java application, because I accidentally had two Range keys annotated (@DynamoDBRangeKey
) in my DAO class, when there should only be one. I changed the new addition's annotation to @DynamoDBAttribute
, and that solved it.
Upvotes: 1
Reputation: 25187
I got this error in Java because I had used the @DynamoDBHashKey
annotation for a RANGE key. I had to use the @DynamoDBRangeKey
annotation for my object's id instead.
Upvotes: 3
Reputation: 621
The following applies to the Node.js AWS SDK in the AWS Lambda environment:
This was a rough one for me. I ran into this problem when trying to use the getItem method. No matter what I tried I would continue to receive this error. I finally found a solution on the AWS forum: https://forums.aws.amazon.com/thread.jspa?threadID=208820
Inexplicably, the apparent solution conflicts with all AWS documentation that I can find.
Here is the code which worked for me:
var doc = require('dynamodb-doc');
var dynamo = new doc.DynamoDB();
var params = { }
params.TableName = "ExampleTable";
var key = { "ExampleHashKey": "1" };
params.Key = key;
dynamo.getItem(params, function(err, data) {
if (err)
console.log(err);
else
console.log(data)
});
Upvotes: 62
Reputation: 3578
I also got this error when I was sending a string instead of an integer.
Of course, this was when I was writing to the database, rather than reading from.
Upvotes: 15
Reputation: 15916
To query on fields which are not the hash key you need to use a Global Secondary Index (GSI). Take a look at this AWS Post for more details on GSI's.
UPDATE Feb 2015: It is now possible to add a GSI to an existing table. See the Amazon Docs for more details.
Sadly you cannot add a GSI to an existing DynamoDB table so you'll need to create a new table and port your data if this is something you really need to query on.
From the DynamoDB FAQ:
Q: How do I create a global secondary index for a DynamoDB table?
All GSIs associated with a table must be specified at table creation time. At this time, it is not possible to add a GSI after the table has been created. For detailed steps on creating a Table and its indexes, see here. You can create a maximum of 5 global secondary indexes per table.
If you do not want to port your data you could consider creating a second DynamoDB table with the email as a hash key and the hash of the parent record to use as a lookup into your main data table but as you can imagine this isn't exactly an optimal solution and it comes with its own headaches of keeping it in synch with your master table.
Upvotes: 26