How to read a table from dynamodb using Java? - java

I created a table in Amazon dynamodb with primary key Issue(String) which has data stored in it.I want to read the values from my table. I'm using the following code..
#DynamoDBTable(tableName="Incident")
AmazonDynamoDBClient dynamoDBClient = new AmazonDynamoDBClient();
String tableName = "Incident";
Table table = dynamoDBClient.getTable("Incident");
Item getItem=dynamoDBClient.getItem();
I'm getting an error when calling the getTable method.... is it a predefined method just like createTable() or do we need to write our own..if so how?
And also what method should be used to read all items in the table..?
I used this link to write some of the code... http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/JavaDocumentAPIItemCRUD.html#JavaDocumentAPIGetItem
I'm new to Java please help..

Scan API can be used to get all the items from the table.
The scan should be done until LastEvaluatedKey is not null which is very important to get all the items. Otherwise, you will not get all the items if the table has many items i.e. the API will return 1 MB of data per scan.
A Scan operation performs eventually consistent reads by default, and
it can return up to 1 MB (one page) of data.
Scan API
Map<String, AttributeValue> lastKeyEvaluated = null;
do {
ScanRequest scanRequest = new ScanRequest()
.withTableName("ProductCatalog")
.withLimit(10)
.withExclusiveStartKey(lastKeyEvaluated);
ScanResult result = client.scan(scanRequest);
for (Map<String, AttributeValue> item : result.getItems()){
printItem(item);
}
lastKeyEvaluated = result.getLastEvaluatedKey();
} while (lastKeyEvaluated != null);

Here is example how to read data using Scan API :
#Override
protected ArrayList<String> doInBackground(String... params) {
String tableName = params[0];
ArrayList<String> tempList = new ArrayList<String>();
AmazonDynamoDBClient dynamoDBClient = new AmazonDynamoDBClient (
new BasicAWSCredentials(Constants.ACCESS_KEY_ID,
Constants.SECRET_KEY));
ScanRequest scanRequest = new ScanRequest()
.withTableName(tableName);
//.withAttributesToGet("name");
com.amazonaws.services.dynamodb.model.ScanResult result = dynamoDBClient.scan(scanRequest);
for (Map<String, AttributeValue> item : result.getItems()) {
tempList.add(item.toString());
//analizeItem(tempList, item);
}
return tempList;
}
Reference from programcreeks

AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().withRegion(Regions.AP_SOUTH_1).build();
DynamoDB dynamoDB = new DynamoDB(client);
Table table = dynamoDB.getTable("Student");
Item item = table.getItem("PK", "portion Key","SK","Sort Key");
System.out.println(item.toJSONPretty());

Related

Search DynamoDB column for a specific string using DynamoDBMapper

I am using DynamoDBMapper to scan a a table, specifically a column named "title". I should be returned a list of blogs that contains a string passed into the scanExpression. This is code I wrote about a year and a half ago which I remember working. Maybe something has been updated since?
Thanks!
public List<BlogDetailsEntity> searchBlogs(String query) {
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
scanExpression.addFilterCondition("title", new Condition()
.withComparisonOperator(ComparisonOperator.CONTAINS)
.withAttributeValueList(new AttributeValue().withS(query.toLowerCase())));
return dynamoDBMapper.scan(BlogDetailsEntity.class, scanExpression);
}
Your code is not best practice anymore. Java V1 and this mapper should be replaced with AWS SDK for Java V2.
To get the latest code for AWS, always refer to the new AWS Code Library here.
Code examples for DynamoDB using AWS SDKs
To filter a column using the V2 enhanced client (a replacement for DynamoDBMapper), you can use DynamoDbEnhancedClient. For example, assume you want to scan a table to get all Closed items on a column named archive.
You can use code like this.
// Get Open items from the DynamoDB table.
public List<WorkItem> getOpenItems() {
// Create a DynamoDbEnhancedClient.
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
.dynamoDbClient(getClient())
.build();
try{
// Create a DynamoDbTable object.
DynamoDbTable<Work> table = enhancedClient.table("Work", TableSchema.fromBean(Work.class));
AttributeValue attr = AttributeValue.builder()
.s("Open")
.build();
Map<String, AttributeValue> myMap = new HashMap<>();
myMap.put(":val1",attr);
Map<String, String> myExMap = new HashMap<>();
myExMap.put("#archive", "archive");
// Set the Expression so only Closed items are queried from the Work table.
Expression expression = Expression.builder()
.expressionValues(myMap)
.expressionNames(myExMap)
.expression("#archive = :val1")
.build();
ScanEnhancedRequest enhancedRequest = ScanEnhancedRequest.builder()
.filterExpression(expression)
.limit(15)
.build();
// Scan items.
Iterator<Work> results = table.scan(enhancedRequest).items().iterator();
WorkItem workItem ;
ArrayList<WorkItem> itemList = new ArrayList<>();
while (results.hasNext()) {
workItem = new WorkItem();
Work work = results.next();
workItem.setName(work.getName());
workItem.setGuide(work.getGuide());
workItem.setDescription(work.getDescription());
workItem.setStatus(work.getStatus());
workItem.setDate(work.getDate());
workItem.setId(work.getId());
// Push the workItem to the list.
itemList.add(workItem);
}
return itemList;
} catch (DynamoDbException e) {
System.err.println(e.getMessage());
System.exit(1);
}
return null;
}
You can find a complete AWS end to end developer tutorial that teaches you how to use this code to display Amazon DynamoDB items in a React client app. For example, this illustration shows Closed items.
This complete doc can be found in the code lib here:
Create an Amazon Relational Database Service item tracker

Exclusive Start Key causing issue with local secondary index in DynamoDbMapper

I have a table in dynamo db.
Below is the key for this table.
partitionKey - campaignId
sortKey - email
I have created a local secondary index for this table.Below is the key for local secondary index
partitionKey - campaignId
sortKey - subStatus
As per the dynamo db you should include primary keys of the table and the index (as key), with last evaluated values (as attribute value) when you setting ExclusiveStartKey.
Below is the code snippet of code.
public QueryResultPage<Prospect> getPaginatedProspectsByCampaignIdAndSubStatus(String campaignId, ProspectSubStatus subStatus, Integer limit, Map<String, AttributeValue> lastEvaluatedKey, String email) {
Prospect prospect = new Prospect();
prospect.setCampaignId(campaignId);
Map<String, AttributeValue> exclusiveStartKey = new HashMap<String, AttributeValue>();
if(!lastEvaluatedKey.isEmpty()) {
exclusiveStartKey.put("campaingId", lastEvaluatedKey.get("campaingId"));
exclusiveStartKey.put("subStatus", lastEvaluatedKey.get("subStatus"));
exclusiveStartKey.put("email", new AttributeValue().withS(email));
}
Condition rangeKeyCondition = new Condition()
.withComparisonOperator(ComparisonOperator.EQ)
.withAttributeValueList(new AttributeValue().withS(subStatus.toString()));
DynamoDBQueryExpression queryExpression = null;
if(exclusiveStartKey.isEmpty()) {
queryExpression = new DynamoDBQueryExpression<Prospect>()
.withHashKeyValues(prospect)
.withIndexName("subStatus-index")
.withRangeKeyCondition("subStatus", rangeKeyCondition)
.withConsistentRead(false).withLimit(limit);
} else {
queryExpression = new DynamoDBQueryExpression<Prospect>()
.withHashKeyValues(prospect)
.withIndexName("subStatus-index")
.withExclusiveStartKey(exclusiveStartKey)
.withRangeKeyCondition("subStatus", rangeKeyCondition)
.withConsistentRead(false).withLimit(limit);
}
QueryResultPage<Prospect> prospects = mapper.queryPage(Prospect.class, queryExpression);
return prospects;
}
But when run it, I am getting below error. Can someone please help me out to understand what I am doing wrong and how can I achieve the pagination in it.

Fetching records from DynamoDB using QuerySpec

In a DynamoDB table where CustomerStatus is a column in which item may contain 'Active','Inactive' or 'Deleted' as CustomerStatus. I want to fetch all customers whose status is 'Active' as well 'Inactive'.
Here is the code sample I am using, but I am not sure how to get it done.
private Object data(MuleEventContext eventContext) {
List<Object> finalJson = new ArrayList<Object>();
String tableName = "Customers";
NameMap nameMap = new NameMap();
nameMap.put("#v_status", "CustomerStatus");
ValueMap valueMap = new ValueMap();
valueMap.put(":v_statusval", "Deleted");
BasicAWSCredentials cre = new BasicAWSCredentials(accesKey,secretKey);
AmazonDynamoDB dynamoDB1 = AmazonDynamoDBClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(cre)).withRegion(Regions.EU_WEST_1).build();
DynamoDB dynamoDB = new DynamoDB(dynamoDB1);
Table table = dynamoDB.getTable(tableName);
QuerySpec querySpec = new QuerySpec().withKeyConditionExpression("#v_status != :v_statusval")
.withNameMap(nameMap)
.withValueMap(valueMap);
ItemCollection<QueryOutcome> items = null;
Iterator<Item> iterator = null;
Item item = null;
try {
items = table.query(querySpec);
iterator = items.iterator();
while (iterator.hasNext()) {
item = iterator.next();
finalJson.add(item.asMap());
}
} catch (Exception e) {
logger.info(e.getMessage());
}
return finalJson;
}
You can't filter on a HASH key.
I would need to know which attribute is the HASH key and which is the RANGE key.
If the CustomerStatus is not the HASH key, the best way is to create a secondary index for this attribute and do 2 different queries:
One for the Active;
Another one for the Inactive.
This is the most efficient way to do this kind of query.
Another way is doing a scan and filtering the attribute, using the IN operand, as stated in Syntax for Condition Expressions. But this will read all data from your table, can be slow, and consume a lot capacity.

Fetch String of map in dynamodb

I have dynamodb table structure as follows:
{
"id": "1",
"skills": {
"skill1": "html",
"skill2": "css"
}
}
I have task to filter by skills value, In order to complete my task wrote java logic as follows:
AmazonDynamoDB client = dynamoDBService.getClient();
DynamoDB dynamoDB = new DynamoDB(client);
Table table = dynamoDB.getTable("dummy");
Map<String, String> attributeNames = new HashMap<String, String >();
attributeNames.put("#columnValue", "skills.skill1");
Map<String, AttributeValue> attributeValues = new HashMap<String, AttributeValue>();
attributeValues.put(":val1", new AttributeValue().withS("html"));
ScanSpec scanSpec = new ScanSpec().withProjectionExpression("skills.skill1")
.withFilterExpression("#columnValue = :val1 ").withNameMap(new NameMap().with("#columnValue", "skills.skill1"))
.withValueMap(new ValueMap().withString(":val1", "html"));
ItemCollection<ScanOutcome> items = table.scan(scanSpec);
Iterator<Item> iter = items.iterator();
while (iter.hasNext()) {
Item item = iter.next();
System.out.println("--------"+item.toString());
}
The mentioned code does not help me out. Any solution ?
You can use a ProjectionExpression to retrieve only specific attributes or elements, rather than an entire item. A ProjectionExpression can specify top-level or nested attributes, using document paths.
for example from AWS:
GetItemSpec spec = new GetItemSpec()
.withPrimaryKey("Id", 206)
.withProjectionExpression("Id, Title, RelatedItems[0], Reviews.FiveStar")
.withConsistentRead(true);
Item item = table.getItem(spec);
System.out.println(item.toJSONPretty());
Simple solution to this problem is:
First fetch all the records from the table.
Then iterate over the list of that object.
Extract the skills from each object.
Wrote your logic to do filtering.
Repeat the loop till the last record.
I found solution,scanSpec should be as follows:
ScanSpec scanSpec = new ScanSpec()
.withFilterExpression("#category.#uid = :categoryuid").withNameMap(new NameMap().with("#category","skills").with("#uid",queryString))
.withValueMap(new ValueMap().withString(":categoryuid", queryString));

DynamoDB DynamoDBQueryExpression mixed Conditional Operator

What is the best way to do complex queries using DynamoDBQueryExpression.
By default the fetch will executed an AND on all the Conditions provided.
How do i execute something like (C1 && C2 && (C3|| C4|| C5))? Is it even possible with DynamoDB java api?
DynamoDB supports the complex conditions using "com.amazonaws.services.dynamodbv2.document.spec.QuerySpec". You can write the AND and OR conditions using FilterExpression.
Please see the example below:-
1) withKeyConditionExpression - For hash key and range key expressions
2) withFilterExpression - For all other attributes (i.e. other than key attributes)
ItemCollection<QueryOutcome> items = null;
QuerySpec querySpec = new QuerySpec();
ValueMap valueMap = new ValueMap();
valueMap.withString(":autoIdVal", autoID);
valueMap.withString(":docTypeVal", docType);
valueMap.withString(":username", username);
valueMap.withString(":comment", comment);
Map<String, String> nameMap = new LinkedHashMap<>();
nameMap.put("#comment", "comment");
querySpec.withKeyConditionExpression("autoID = :autoIdVal").withFilterExpression("(docType = :docTypeVal AND username = :username) OR (#comment = :comment)")
.withValueMap(valueMap)
.withNameMap(nameMap);
items = table.query(querySpec);
Iterator<Item> iterator = items.iterator();
Item itemData = null;
while (iterator.hasNext()) {
itemData = iterator.next();
System.out.println("Json data ====================>" + itemData.toJSONPretty());
}

Categories

Resources