Query using only partition key in DynamoDB - node.js

I am trying to query on my table using only the partition key and ignoring the sort key but I get no items.
My global secondary index looks like this:
And my table looks like this:
And this is my query:
const params = {
ExpressionAttributeValues: {
':app': 'app',
},
IndexName: 'glc-development-gsi1',
KeyConditionExpression: 'sk = :app',
TableName: this.tableName,
};
return new Promise((resolve, reject) => {
this.client.query(params, (err, data) => {
console.log(data);
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
According to all the documentation I've read and the other questions on here, this should work and I can't understand why it doesn't. The scan from my index is also empty.

Finally found my solution. DynamoDB stores data in indexes only when both the partition key and the sort key are defined, so my index was empty all the time. The query was fine.

Related

DynamoDB - Delete Item based on ConditionExpression on Sort Key

Is it possible to delete records from dynamodb based on PrimaryKey and ConditionExpression on SortKey?
Following code sample is throwing an exception for me
DeleteVideoCall = async function (pk, sk) {
let params = {
TableName: this._tableName,
Key: {
pk: { S: pk.toString() },
sk: { S: sk.toString() }
},
ConditionExpression: "begins_with(sk,:sk)",
ExpressionAttributeValues: {
":sk" : { S: sk.toString() + "_" }
}
};
return this._ddb
.deleteItem(params)
.promise()
.then((data) => {
console.log(`Video Call '${pk}/${sk}' deleted`);
return null;
})
.catch((error) => {
console.error(
`Error deleting video room '${pk}/${sk}' (${error})`
);
throw error;
});
};
I want to delete all records that begins_with sk and . For example if sk is 560622 then delete all records where sk begins_with 560622
with the code above I get this error:
Error deleting video room '10900/560622'
(ConditionalCheckFailedException: The conditional request failed)
You can't do that. You need whole key to perform a delete. What you can do:
query items (limit retrieved properties to your PK and SK)
use batch-write to remove multiple items, it also accepts delete requests

How to delete multiple rows in DynamoDB?

I am attempting to delete data from a DynamoDB table.
If I delete data using a partition key, it works.
But when I delete multiple rows using any other fields, it fails.
var params = {
TableName: "test",
Key: {
dmac: dmac,
},
ConditionExpression: "dmac= :dmac"
};
docClient.delete( params, (error) => {
if (error) {
console.log( "Delete data fail" );
} else {
console.log( "Delete data Success" );
}
});
Items (or rows) in DynamoDB are uniquely identified by their primary key. A table can have a simple primary key (a partition key) or a composite primary key (a partition key plus a sort key).
To delete an item, you must provide the full primary key (whether it's a simple partition key or composite partition key plus sort key).
So, if you want to delete items that meet a specific condition, for example cars with maxspeed < 120, then issue a query or scan to identify those items, retrieve the primary keys, and then delete the items in a second operation.
To delete a single item, use DeleteItem. To delete multiple items, use BatchWriteItem. Despite the naming of BatchWriteItem, it can be used to put multiple items or to delete multiple items, and you can target one or more DynamoDB tables in the same API call.
Here is an AWS SDK v2 example of deleting multiple items:
const aws = require("aws-sdk");
const ddb = new aws.DynamoDB({ region: "us-east-1" });
(async () => {
const params = {
RequestItems: {
albums: []
}
};
params.RequestItems.albums.push({
DeleteRequest: {
Key: {
pk: { S: "The Who" },
sk: { S: "Tommy" }
}
}
});
params.RequestItems.albums.push({
DeleteRequest: {
Key: {
pk: { S: "The Beatles" },
sk: { S: "Abbey Road" }
}
}
});
await ddb.batchWriteItem(params).promise();
})();
Here is an AWS SDK v3 example of deleting multiple items:
const {
BatchWriteItemCommand,
DynamoDBClient
} = require("#aws-sdk/client-dynamodb");
(async () => {
const client = new DynamoDBClient({ region: "us-east-1" });
const params = {
RequestItems: {
albums: []
}
};
params.RequestItems.albums.push({
DeleteRequest: {
Key: {
pk: { S: "The Who" },
sk: { S: "Tommy" }
}
}
});
params.RequestItems.albums.push({
DeleteRequest: {
Key: {
pk: { S: "The Beatles" },
sk: { S: "Abbey Road" }
}
}
});
await client.send(new BatchWriteItemCommand(params));
})();
in DynamoDB you can only delete an item using its key (that is: the partition key and the sort key, if it is defined on the table). This is, for example, underlined by the fact that the Key attribute is a required attribute in the canonical specification of the delete operation. See: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html#DDB-DeleteItem-request-Key
This means that if you want to delete an item using other attributes you must first lookup the item by the attributes you do have, extract the key from the returned item, and then delete the item using that key.
The standard solution for "looking up an item by attributes that are not the item's key" is to define a global secondary index (GSI) on the table with those attribute(s) defined as the GSI's key.

Get criteria not match the schema

Im trying to get an Item from DynamoDB based on Primary Key but it throws me an exception:
ValidationException: The provided key element does not match the schema
Here is how my table looks:
I'm following a tutorial and here is how I wrote my get:
let params = {
TableName: process.env.CALL_NAVEGATION_HISTORY_TABLE,
Key: {
"Id": requestBody.CallSid
}
}
dynamoDb.get(params, function(err, data) {
if(err){
console.log('Error on dynamodb', err);
callback(null, Helpers.xmlTwimlResponse(twiml));
}
console.log(data);
callback(null, Helpers.xmlTwimlResponse(twiml));
});
What is wrong on my code?
Sometimes the most obvious thing is what we miss right in front of our eyes.
let params = {
TableName: process.env.CALL_NAVEGATION_HISTORY_TABLE,
Key: {
"Id": requestBody.CallSid
}
}
The Key name is case-sensitive. If you change it to 'id' it should work fine.

Query CosmosDB with NodeJS

I am tying to query an existing Azure CosmosDB database with NodeJS.
getItems: function (callback) {
var self = this;
var querySpec = {
query: 'SELECT * FROM root'
};
self.client.queryDocuments(self.collection._self, querySpec).toArray(function (err, results) {
if (err) {
console.log(err.body);
callback(err);
} else {
callback(null, results);
}
});
}
For some reason it is keep complaining about Cross Partition Query. I am not really sure what it is. Any ideas where I may find this Partition Key and how to set it? Also, how can I avoid this exception in the query?
Full error message: Cross partition query is required but disabled. Please set x-ms-documentdb-query-enablecrosspartition to true, specify x-ms-documentdb-partitionkey, or revise your query to avoid this exception.
P.S. I know there are few similar questions asked already, but none of them addresses with NodeJS.
You're getting this error because the document collection you're querying against is a partitioned collection.
In order to query against a partitioned collection, you would either need to specify a partition against which to execute the query or specify that you want to query across partitions. BTW, former is recommended.
For cross-partition queries, you would need to specify the same in options. So your code would be:
getItems: function (callback) {
var self = this;
var querySpec = {
query: 'SELECT * FROM root'
};
const options = {//Query options
enableCrossPartitionQuery: true
};
self.client.queryDocuments(self.collection._self, querySpec, options).toArray(function (err, results) {
if (err) {
console.log(err.body);
callback(err);
} else {
callback(null, results);
}
});
}
If you're querying against a single partition, you will need to specify the partition key value in the query. In this case, your options would look something like:
const options = {
partitionKey: 'partition-key-value'
};

DynamoDB scanning using filter

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.

Resources