I am trying to use Dynamodb on a new project and i have to say i am very confused.
So i have setup a new table with a hash key called ID which i am setting as a timestamp as it needs to be unique.
I am then inserting my data as follow with Lambda
var tableName = "TrackerTable";
var datetime = new Date().getTime().toString();
var putData = {
"TableName": tableName,
"Item": {
"ID" : {
"N": datetime
},
"TrackIt": {
"S": event.trackit
},
"Latitude": {
"N": event.lat
},
"Longitude": {
"N": event.lon
},
"Time": {
"N": datetime
}
}
}
dynamoDB.putItem(putData, function(err, data) {
if (err) {
context.fail('ERROR: Dynamo failed: ' + err);
} else {
console.log('Dynamo Success: ' + JSON.stringify(data, null, ' '));
context.succeed('SUCCESS');
}
});
So my table starts to look like this which is fine.
So i am trying to use Lambda to return my results based on the trackit column?
I have the following code which doesnt work.
var tableName = "TrackerTable";
var datetime = new Date().getTime().toString();
var queryData = {
"TableName": tableName,
"ConsistentRead": true,
"KeyConditionExpression": "trackit = :val",
"ExpressionAttributeValues": {":val": {"S": "05LUGFr7494"}}
};
dynamoDB.query(queryData, function(err, data) {
if (err) {
context.fail('ERROR: Dynamo failed: ' + err);
}else{
console.log('Dynamo Success: ' + JSON.stringify(data, null, ' '));
context.done(null, data.Items);
}
});
I get this error.
{
"errorMessage": "ERROR: Dynamo failed: ValidationException: Query condition missed key schema element: ID"
}
How can i query all the trackit values i cant add the ID value as it will only return one value?
Very confused.
The way you have your table setup I think you'll need to do a scan here instead of a query[1]. If this is an operation that your will be doing frequently and want to have the ability to do a query, you would need to add the trackit property as one of your secondary indexes.
[1] http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/QueryAndScan.html
Related
I'm trying to query Dynamo DB for person_id between two dates. I have errors with the following code:
Please note that the primary key of the table is (event_id), but I'm not sure how/where to use it?
var params = {
TableName: "tableName",
IndexName: "person_id-event_date-index",
FilterExpression: "#person_id =:person_id",
KeyConditionExpression: "#person_id = :person_id and #event_date BETWEEN :from AND :to",
ExpressionAttributeNames: {
"#person_id": "person_id",
"#event_date": "event_date"
},
ExpressionAttributeValues: {
":person_id": person_id,
":from": start_date,
":to": end_date
}
}
documentClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
callback(new Error(JSON.stringify(err)))
}
else {
callback(null, data);
}
});
Can anyone please check how to make this working?
Many thanks
Short answer, you cannot do that unless the Table has some GSI (Global Secondary Indexes) set up that allow for that sort of query.
When doing a query you must pass a primary key value, you cannot do a query otherwise.
Considering that you want to query based on a different column, not the primary key, you need to see if you have an index defined with
PrimaryKey = person_id and
RangeKey = event_date
If such an index is note defined you may rely on scan, but that's not recommended.
Here is the fix code:
var params = {
TableName: "tableName" ,
IndexName: "person_id-event_date-index",
KeyConditionExpression: "#person_id = :person_id and #event_date BETWEEN :from AND :to",
ExpressionAttributeNames: {
"#person_id": "person_id",
"#event_date": "event_date"
},
ExpressionAttributeValues: {
":person_id": person_id,
":from": start_date,
":to": end_date
}
}
documentClient.query(params, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
callback(new Error(JSON.stringify(err)))
}
else {
callback(null, data);
}
});
}
I have a table with an attribute with name id and of type HASH. I want to get all items from a array of id's.
{
TableName: `MyTable`,
FilterExpression: 'id IN (:id)',
ExpressionAttributeValues: { ':id': ids },
};
What should I do to get all items by my ids?
You can also use DocumentClient and batchGet.
const AWS = require('aws-sdk');
const documentClient = new AWS.DynamoDB.DocumentClient();
let queryParams = {RequestItems: {}};
queryParams.RequestItems['tableName'] = {
Keys: [{'id': 'Value1'}, {'id': 'value2'}],
ProjectionExpression: 'id' //define other fileds that you have Ex: 'id,name'
};
documentClient.batchGet(queryParams, function (err, data) {
if (err) {
console.log('failure:getItemByBatch data from Dynamo error', err);
} else {
console.log('success:getItemByBatch data from Dynamo data');
console.log(data)
}
});
Please use BatchGetItem API to get multiple values from DynamoDB table.
BatchGetItem
Example:-
var dynamodb = new AWS.DynamoDB({maxRetries: 5, retryDelayOptions: {base: 300} });
var table = "Movies";
var year_val = 2015;
var title = "The Big New Movie";
var params = {
"RequestItems" : {
"Movies" : {
"Keys" : [ {
"yearkey" : {N : "2016"},
"title" : {S : "The Big New Movie 1"}
} ]
}
},
"ReturnConsumedCapacity" : "TOTAL"
};
dynamodb.batchGetItem(params, function(err, data) {
if (err) {
console.error("Unable to get item. Error JSON:", JSON.stringify(err,
null, 2));
} else {
console.log("Movie data:", JSON.stringify(data, null, 2));
}
});
Its in C#, below code is to get all items by an array of ids from a dynamodb table having different guid's using BatchGet or CreateBatchGet
string tablename = "AnyTableName"; //table whose data you want to fetch
var BatchRead = ABCContext.Context.CreateBatchGet<ABCTable>(
new DynamoDBOperationConfig
{
OverrideTableName = tablename;
});
foreach(string Id in IdList) // in case you are taking string from input
{
Guid objGuid = Guid.Parse(Id); //parsing string to guid
BatchRead.AddKey(objGuid);
}
await BatchRead.ExecuteAsync();
var result = BatchRead.Results;
// ABCTable is the table modal which is used to create in dynamodb & data you want to fetch
Im new to DynamoDB and have a table which is "feeds" and partition key is "id" and i have 3 other attributes which are "category", "description", "pubDate".
I want to query the "category" attribute. But it doesn't work, because i can only query the partition key (hashkey), if im right.
Now my query is that which doesnt work;
let category = event.category;
const params = {
Key: {
"category": {
S: category
}
},
TableName: "feeds"
};
dynamodb.getItem(params, function (err, data) {
if (err) {
console.log(err);
callback(err);
}
else {
console.log(data);
callback(null, data);
}
});
How can i make it work? I tried to write a scan query but i couldn't understand the documentation of AWS good.
Edit: I did make it work with the help of Dunedan. Here is the working code,
var params = {
TableName: 'feeds',
IndexName: 'category-index',
KeyConditionExpression: 'category = :category',
ExpressionAttributeValues: {
':category': 'backup',
}
};
var docClient = new AWS.DynamoDB.DocumentClient();
docClient.query(params, function(err, data) {
if (err) callback(err);
else callback(null, data);
});
If your application will regularly query for the category, you should check out Global Secondary Indexes (GSI), which allow you to generate a projection of your data with another key than the original hash key as the key you can use to query.
Scanning and filtering as you suggested doesn't scale very well, as it fetches all data in the table and just filters the results.
I am facing some issue with querying data from DynamoDB can any one of you help me on this? I am coding in NodeJS.
My table looks like below with,
Primary key: RequestId
Secondary index: Userid with sortkey Timestamp
When I am pulling the data using UserId, I am getting lot's for records so, planning to pull the data with Timestamp condition.
RequestId Request Timestamp UserId
var doc = require("dynamodb-doc");
var dynamo = new doc.DynamoDB();
var userid_col = "amzn1.ask.account.AGCAPY7JBHQWHTNGAHJJ";
var databaserec = { TableName: "dna_cdknow_prod_historylog",
IndexName: "UserId-TimeStamp-index",
KeyConditionExpression: "UserId = :input",
FilterExpression : 'created between :val1 and :val2',
ExpressionAttributeValues:{ ":input": userid_col, ":val1" : "2016-05-23T00:00:00Z", ":val2" : "2017-05-23T16:20:49Z" } };
The below code should work if the GSI definition is as follows:-
UserId - Partition key of GSI
created - Sort key of GSI
Corrected code:-
var databaserec = {
TableName: "dna_cdknow_prod_historylog",
IndexName: "UserId-TimeStamp-index",
KeyConditionExpression: "UserId = :input AND created between :val1 and :val2'",
ExpressionAttributeValues:{ ":input": userid_col, ":val1" : "2016-05-23T00:00:00Z", ":val2" : "2017-05-23T16:20:49Z" }
};
docClient.query(databaserec, function(err, data) {
if (err) {
console.error("Unable to query. Error:", JSON.stringify(err, null, 2));
} else {
console.log(params);
console.log("Query succeeded.");
data.Items.forEach(function(item) {
console.log("Item :" + JSON.stringify(item));
});
}
});
I need to update my dynamo db table by using only partition key. But i got validation exeption.
I have created a table with 3 fields.
id (Partition Key)
name (Sort Key)
age
Then i have triyed to update age field using only id.(tryied to modify age 30 to 40) this is my code
var AWS = require("aws-sdk");
AWS.config.update({
region: "us-east-1",
});
var params = {
TableName: 'test',
Key: { id: '100' },
UpdateExpression: 'set #age = :age ',
ConditionExpression: '#age = :testAge',
ExpressionAttributeNames: { '#age': 'age' },
ExpressionAttributeValues: { ':age': '40', ':testAge': '30' }
};
var docClient = new AWS.DynamoDB.DocumentClient();
docClient.update(params, function (err, data) {
if (err) {
console.log(err);
}
else {
console.log(data);
}
});
But i got error like this.
{ [ValidationException: The provided key element does not match the schema]
message: 'The provided key element does not match the schema',
code: 'ValidationException',
time: Thu Nov 17 2016 22:38:01 GMT+0530 (IST),
requestId: '34PNMFM6CEACQIRHTSV77OI0JRVV4KQNSO5AEMVJF66Q9ASUAAJG',
statusCode: 400,
retryable: false,
retryDelay: 0 }
After getting error, i modified my params variable like this
var params = {
TableName: 'test',
Key: { id: '100',name: 'manaf' },
UpdateExpression: 'set #age = :age ',
ConditionExpression: '#age = :testAge',
ExpressionAttributeNames: { '#age': 'age' },
ExpressionAttributeValues: { ':age': '40', ':testAge': '30' }
};
Using this, updation is successfully completed. How to update table using without sort key?
Currently, the DynamoDB update API doesn't have an option to update the item by partition key only. There is no batchUpdateItem API similar to batchWriteItem as well.
So, if the sort key is not available, get all the sort keys of partition key and update each item for the partition and sort key combination.
For the primary key, you must provide all of the attributes. For
example, with a simple primary key, you only need to provide a value
for the partition key. For a composite primary key, you must provide
values for both the partition key and the sort key.
Sample code:-
You may need to change it for your table. The below code uses "Movies" table which has "yearkey" as partition key and "title" as sort key.
The below code updates the "createdate" attribute for the given hash key "2012".
The variable paramsUpdate is formed based on the query operation. Please update it accordingly for your requirement (i.e. table structure). Logic remains same, you just need to change the table name and key values accordingly.
var AWS = require("aws-sdk");
var creds = new AWS.Credentials('akid', 'secret', 'session');
AWS.config.update({
region : "us-west-2",
endpoint : "http://localhost:8000",
credentials : creds
});
var docClient = new AWS.DynamoDB.DocumentClient();
var hashKey = 2012;
var paramsQuery = {
TableName : "Movies",
KeyConditionExpression : 'yearkey = :hkey',
ExpressionAttributeValues : {
':hkey' : hashKey
}
};
function updateItem(paramsUpdate) {
console.log("Updating the item...");
docClient.update(paramsUpdate, function(err, data) {
if (err) {
console.error("Unable to update item. Error JSON:", JSON.stringify(
err, null, 2));
} else {
console.log("UpdateItem succeeded:", JSON.stringify(data));
}
});
}
docClient.query(paramsQuery, function(err, data) {
if (err) {
console.error("Unable to read item. Error JSON:", JSON.stringify(err,
null, 2));
} else {
console.log(data.Count);
var itemIndex = 0;
while (itemIndex < data.Count) {
console.log('Hashkey to be updated ======>',
data.Items[itemIndex].yearkey,
';Title to be updated ========>',
data.Items[itemIndex].title);
var paramsUpdate = {
TableName : "Movies",
Key : {
"yearkey" : data.Items[itemIndex].yearkey,
"title" : data.Items[itemIndex].title
},
UpdateExpression : "set #createdate = :createdate",
ExpressionAttributeNames : {
'#createdate' : 'createdate'
},
ExpressionAttributeValues : {
':createdate' : '2016-11-17'
},
ReturnValues : 'UPDATED_NEW'
};
updateItem(paramsUpdate);
itemIndex++;
}
}
});
In DynamoDB, partition key + sort key is treated as a "composite primary key", which uniquely identifies an item (on the contrary, Dynamo also supports simple primary key, which only contains partition key). So you need both to update an item. This is the reason that you can have two items with the same partition key but different sort key. So if you only provide the partition keys, Dynamo will get confused with which item to update.
For your current table configuration, the only way to update an item given a partition key is to make a query with only partition key to get all the items, and filter out the one with the intended sort key. Then use the combination of partition key and sort key to update this item.