I'm starting to learn Dynamodb here, and currently trying to do a search on my table where PK is the partition key and SK is the range key. PK contains an email address, whereas SK contains value like AB_STATE
, BC_STATE
, MY_STATE
. So I want to search in the SK where the value starts with MY_
but I'm not entirely sure how to do it using .get()
function.
Here's my query Seller.get({ "PK": "imin@cats.com", "SK" : "MY" })
which obviously isn't doing what I wants.
I am aware that I maybe can use filter like below, but I read in many places that using filter is not recommended (?)
var filter = new dynamoose.Condition().where("PK").eq(email).filter("SK").beginsWith("MY_");
var premiseProfile = await Seller.query(filter).exec()
Below is the schema for my Seller table
const schema = new dynamoose.Schema({
PK: {
type: String,
hashKey: true,
},
SK: {
type: String,
rangeKey: true,
},
"firstName": String,
"lastName": String,
"gender": {
"type": Number,
"default": 0
},
}, {
"saveUnknown": true,
"timestamps": true
});
When doing a Model.get
call you must pass in an entire key. You can not pass in a key that starts with. This is due to the fact that Model.get
will only return 1 item, and the query indicates that you could have multiple items there.
It's hard to answer your question exactly due to the fact that you didn't post your schema. But it looks like doing a query
in this case isn't bad due to the fact that you are querying the data as opposed to filtering it.
Little bit more information based on comments.
I realized the condition.filter
documentation doesn't really cover this as well as it should. Basically depending on your schema, it will determine the best index, and optimize it the best way it knows how.
For example, if you have the following code:
const dynamoose = require("dynamoose");
(async () => {
dynamoose.model.defaults.set({
"create": false,
"waitForActive": false
});
const schema = new dynamoose.Schema({
"PK": {
"type": String,
"hashKey": true
},
"SK": {
"type": String,
"rangeKey": true
}
});
const Model = dynamoose.model("User", schema);
dynamoose.logger.providers.add(console);
const filter = new dynamoose.Condition().where("PK").eq("test@test.com").filter("SK").beginsWith("MY_");
const premiseProfile = await Model.query(filter).exec()
})();
It will produce the following output:
aws:dynamodb:query:request - {
"ExpressionAttributeNames": {
"#qha": "PK",
"#qra": "SK"
},
"ExpressionAttributeValues": {
":qhv": {
"S": "test@test.com"
},
":qrv": {
"S": "MY_"
}
},
"TableName": "User",
"KeyConditionExpression": "#qha = :qhv AND begins_with (#qra, :qrv)"
}
As you can see it's using KeyConditionExpression
as opposed to FilterExpression
.
So you aren't filtering. If it makes more sense for you, you can use condition.where
or condition.attribute
.
It's important to note that in some cases it will use FilterExpression
. But it will first look at your schema and try to see if it can use KeyConditionExpression
, if it can, it'll use that, otherwise it'll use FilterExpression
.