I have a DynamoDB messages table with id, content, createdAt (int), userID fields.
I can obtain a user's messages using below resolver:
{
"version" : "2017-02-28",
"operation" : "Query",
"index" : "userid-createdat-index",
"query" : {
"expression": "userID = :userID",
"expressionValues" : {
":userID" : $util.dynamodb.toDynamoDBJson($context.arguments.userID)
}
}
}
My objective is to get user messages within the last 5 seconds using the createdAt field which is epoch time in milliseconds. I would like to avoid using Scan operation as my table will be large.
How do I do that? What kind of DynamoDB index do I need for it?
Assuming the id field is unique, you need to create the table partition key on id then a Global Secondary Index on (userID , createdAt). The query to access the result that you are looking for should look something like this --key-condition-expression "userID = :userID and createdAt >= :createdAt"
Table creation
aws dynamodb create-table \
--table-name messages \
--attribute-definitions \
AttributeName=id,AttributeType=S \
AttributeName=userID,AttributeType=S \
AttributeName=createdAt,AttributeType=N \
--key-schema AttributeName=id,KeyType=HASH \
--provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5 \
--global-secondary-indexes \
"[{\"IndexName\": \"UserIDIndex\",
\"KeySchema\": [{\"AttributeName\":\"userID\",\"KeyType\":\"HASH\"},
{\"AttributeName\":\"createdAt\",\"KeyType\":\"RANGE\"}],
\"Projection\":{\"ProjectionType\":\"ALL\"},
\"ProvisionedThroughput\": {\"ReadCapacityUnits\":10,\"WriteCapacityUnits\":10}}]"
Example query with GSI
aws dynamodb query \
--table-name messages \
--index-name UserIDIndex \
--key-condition-expression "userID = :userID and createdAt >= :createdAt" \
--expression-attribute-values '{":userID":{"S":"u1"} , ":createdAt":{"N":"2"} }'
More information on GSI can be found here
if you are running DynamoDB locally you can add --endpoint-url http://localhost:8000 to both of the above code snippets.
Using suggestions from CruncherBigData's answer, I successfully run such a query.
I created an index with a partition key for userID and a sort key with createdAt. My mistake here was forgetting to select Number as a data type for createdAt during index creation. Keeping it as a String failed my query.
I then used a query resolver to check messages of a user in the last 5 seconds:
#set( $messageTimeLimit = 5000 )
#set( $lastNSeconds = $util.time.nowEpochMilliSeconds() - $messageTimeLimit )
{
"version" : "2018-05-29",
"operation" : "Query",
"index" : "userID-createdAt-index",
"query" : {
"expression": "userID = :userID and createdAt >= :lastFiveSeconds",
"expressionValues" : {
":lastFiveSeconds" : $util.dynamodb.toDynamoDBJson($lastFiveSeconds),
":userID" : $util.dynamodb.toDynamoDBJson($context.arguments.userID)
}
}
}
Related
When writing to DynamoDB or reading from DynamoDB you can specify: ReturnConsumedCapacity.
When you do this the API does return total CapacityUnits, but I am not able to get it to return ReadCapacityUnits or WriteCapacityUnits. The documentation indicates we should indeed get data on RCUs and WCUs: https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ConsumedCapacity.html
This is true whether or not you set ReturnConsumedCapacity to TOTAL or INDEXES.
This is also true if you are simply doing a read query too.
Is there anyway to get RCUs and WCUs returned?
Here is a sample query:
aws.exe dynamodb query \
--table-name tableName \
--index-name GSI1 \
--key-condition-expression "GSI1PK = :pk" \
--expression-attribute-value '{":pk": {"S": "blah"}}' \
--return-consumed-capacity TOTAL
which returns something like this:
"ConsumedCapacity": {
"TableName": "tableName",
"CapacityUnits": 128.5
}
If I change the request from TOTAL to INDEXES I get:
"ConsumedCapacity": {
"TableName": "oaas-performance-table-dev",
"CapacityUnits": 128.5,
"Table": {
"CapacityUnits": 128.5
}
}
}
pretty much the same in other words. No RCU or WCU.
Any idea how to get this additional data?
This is the intended behavior, per the Query docs:
TOTAL - The response includes only the aggregate ConsumedCapacity for the operation.
A query can only consume read capacity, so CapacityUnits is effectively the same thing as ReadCapacityUnits, and WriteCapacityUnits is always 0.
I'm able to search using
GET /api/search/prop?[p1=v1,v2][&p2=v3][&repos=x[,y]]
as per the documentation. But how to use optional headers to get extra information for the found artifacts?
You need to set the HTTP header X-Result-Detail to properties. Using a curl command it would look something like this
curl -uUSERNAME:PASSWORD --request GET \
--url 'http://jfrog.local/artifactory/api/search/prop?build.number=1&repos=generic-prod' \
--header 'X-Result-Detail: properties'
This will look in my repository called generic-prod for all artifacts that have build.number = 1 as a property.
That would return with the results you're looking for
{
"results" : [ {
"properties" : {
"build.name" : [ "docker-jenkins-build" ],
"build.number" : [ "1" ],
"build.timestamp" : [ "1556557591780" ]
},
"uri" : "http://jfrog.local:80/artifactory/api/storage/generic-prod/jenkins.zip"
} ]
}
This lists the properties I have for my artifact.
I am trying below command after aws
--configure command:
aws dynamodb create-table
--table-name MusicCollection2
--attribute-definitions
AttributeName=Artist,AttributeType=S AttributeName=SongTitle,AttributeType=S --
key-schema AttributeName=Artist,KeyType=HASH AttributeName=SongTitle,KeyType=RANGE
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5
Output: Nothing
Please give suggestion how to create dyanmodb table using AWS CLI.
Create the JSON file create-table-movies.json with the below content
{
"TableName": "MusicCollection2",
"KeySchema": [
{ "AttributeName": "Artist", "KeyType": "HASH" },
{ "AttributeName": "SongTitle", "KeyType": "RANGE" }
],
"AttributeDefinitions": [
{ "AttributeName": "Artist", "AttributeType": "S" },
{ "AttributeName": "SongTitle", "AttributeType": "S" }
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 5,
"WriteCapacityUnits": 5
}
}
Browse to the file path on DOS command prompt (assuming Windows OS) and execute the below command
Creates the table on local DynamoDB:-
aws dynamodb create-table --cli-input-json file://create-table-movies.json --endpoint-url http://localhost:8000
To create the table on AWS DynamoDB service, please provide the correct region name. If your config is done already, it should work.
aws dynamodb create-table --cli-input-json file://create-table-movies.json --region us-west-2
AWS CLI Configure:-
$ aws configure
AWS Access Key ID [None]: accesskey
AWS Secret Access Key [None]: secretkey
Default region name [None]: us-west-2
Default output format [None]:
Once you execute the above command, it updates the data on your profile (on windows).
C:\Users\<username>\.aws\
Check the following files:-
config - should have the region name
credentials - should have access key and secret key
Credentials Sample:-
[default]
aws_access_key_id = aaaadffewe
aws_secret_access_key = t45435egfdg456retgfg
Config File Sample:-
[default]
region = us-east-1
aws dynamodb create-table --table-name contact --attribute-definitions AttributeName=name,AttributeType=S AttributeName=email,AttributeType=S --key-schema AttributeName=name,KeyType=HASH AttributeName=email,KeyType=RANGE --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
Use this command instead.
I wants to delete all the existing tables in my database in DynamoDb?
Is there any way to do it?
You can use aws cli to delete all tables, may be except one table.
aws dynamodb list-tables --profile your_profile | jq .'TableNames[]' -r | grep -v table_you_dont_want_to_delete | xargs -ITABLE -n 1 aws dynamodb delete-table --table-name TABLE --profile your_profile
You can delete table using below code.
var params = {
TableName: 'table-name',
};
dynamodb.deleteTable(params, function(err, data) {
if (err) ppJson(err); // an error occurred
else ppJson(data); // successful response
});
You have 2 options:
Manually go into the AWS console and delete every table
Programmatically by calling ListTables (multiple calls if pagination is needed), iterate through the resulting TableNames, and call DeleteTable for each one.
Javascript to delete all tables
var AWS = require("aws-sdk")
AWS.config.update({
region: "us-west-2",
endpoint: process.env.DYNAMODB_URL
})
var dynamodb = new AWS.DynamoDB();
dynamodb.listTables({}, function(err, data) {
if (err) console.error(err, err.stack)
for (tableName of data.TableNames) {
dynamodb.deleteTable({TableName: tableName}, function(err, data) {
if (err) console.error(err, err.stack)
else console.log('Deleted', tableName)
})
}
})
The new UI console (2020) now allows you to select multiple tables and delete.
require 'json'
tables=JSON.parse(`aws dynamodb list-tables`)["TableNames"]
tables.each do |table|
`aws dynamodb delete-table --table-name #{table}`
sleep 2 # Only 10 tables can be created, updated, or deleted simultaneously
puts "#{table} deleted"
end
To delete all the DynamoDB tables having a specific keyword in their names, simply run the following CLI commands:
tableList=$(aws dynamodb list-tables | jq .'TableNames[]' -r | grep tableNameKeyword)
for table in $tableList; do aws dynamodb delete-table --table-name $table ; done
I have a dataset uploaded in following form:
SomeKey
-> Alphabet
-Emp1: "{ 'Fname' : 'Bob', 'Lname' : 'Sob' }"
-Emp2: "{ 'Fname' : 'Tom', 'Lname' : 'Mot }"
Now using Rest API, I want to edit Fname and Lname of employee with key Emp1 to Fred and Dref, and Fname and Lname of employee with key Emp2 to Kent and Tenk in one single call. Is this possible? If yes, how?
If you would like to update a single employee, you can do so with a PUT REST API call like this:
curl -X PUT -d <data> https://some.url.com/SomeKey/Employees/Emp1/.json
If would like to update multiple employees using a single REST API call, you can do so with a PATCH REST call like this:
curl -X PUT -d '{"Emp1":<data1>,"Emp2":<data2>"}' \
https://some.url.com/SomeKey/Employees/.json
Additional details about the REST API are available here:
https://www.firebase.com/docs/rest-api.html