i read the following link that explains to use placeholders by means of expression attribute name
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ExpressionPlaceholders.html#ExpressionAttributeValues
My json document is stored as follows:
{"user_json": {"profile.title":"abc"} }"
my java code is as follows
Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#u1", "user_json.profile.title");
String projectionExpression = "user_id, #u1";
QuerySpec spec = new QuerySpec()
.withProjectionExpression(projectionExpression)
.withKeyConditionExpression("user_id = :v_id")
.withNameMap(expressionAttributeNames)
.withValueMap(new ValueMap()
.withString(":v_id", userId))
.withConsistentRead(true);
ItemCollection<QueryOutcome> items = table.query(spec);
Iterator<Item> iterator = items.iterator();
String jsonPretty="";
while (iterator.hasNext()) {
jsonPretty = iterator.next().toJSON();
System.out.println(jsonPretty);
}
Problem: not able to retrieve Document path which has a dot in it.
can someone please point out the problem? thanks
Try doing like this:
Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#u1_1", "user_json");
expressionAttributeNames.put("#u1_2", "profile.title");
String projectionExpression = "user_id, #u1_1.#u1_2";
Related
I'm trying to figure out how to make a conditional delete of an item. Assume a table with the attributes (account, system, secret). Let's say that I have the following code:
String mySecret = ...
final Map<String, AttributeValue> key = new HashMap<String, AttributeValue>();
key.put("account", AttributeValue.builder()
.s(account).build());
key.put("system", AttributeValue.builder()
.s(system).build());
DeleteItemRequest request = DeleteItemRequest.builder()
.tableName(DYNAMODB_TABLE_NAME)
.key(key)
.build();
I'd like the DeleteItemRequest to succeed only if the value of mySecret matches the value of the attribute secret of the row to be deleted. How do I specify this in the DeleteItemRequest?
Your request arguments should look something like this (in pseudocode):
{
"TableName": "YOUR_TABLE",
"Key": {
"PK": "PARTITION_KEY",
"SK": "SORT_KEY"
},
"ConditionExpression": "#secretKey = :secretValue",
"ExpressionAttributeNames": {"#secretKey":"secret"},
"ExpressionAttributeValues": {":secretValue": {"S":"mySecret"}}
}
I believe you're missing a ConditionExpression from the DeleteItemRequest. It should look something like this. I've not used Java to work with DDB, so there's probably a better way of doing this, but...
Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#secretKey", "mySecret");
Map<String, AttributeValue> expressionAttributeValues = new HashMap<String, AttributeValue>();
expressionAttributeValues.put(":secretValue", new AttributeValue("secret"));
String conditionExpression = "#secretKey = :secretValue";
deleteItemRequest.setConditionExpression(conditionExpression);
deleteItemRequest.setExpressionAttributeNames(getExpressionAttributeNames());
deleteItemRequest.setExpressionAttributeValues(getExpressionAttributeValues());
Oh, and keep in mind that system is a reserved word in DDB.
I am trying to get the data from DynamoDB based on a few filters. (e.g.: get me a record where the productNumber and colorwayNumber is 'A', 'B'.) Following is the code snippet:
AmazonDynamoDB amazonDynamoDB = DynamoDBClient.getInstance().getConnection();
Map<String, HashMap<String, String>> attrVal = new HashMap<String, HashMap<String, String>>();
Map<String,String> expressionAttributesNames = new HashMap<>();
expressionAttributesNames.put("#colorwayNumber","colorwayNumber");
expressionAttributesNames.put("#productNumber","productNumber");
Map<String,AttributeValue> expressionAttributeValues = new HashMap<>();
expressionAttributeValues.put(":colorwayNumber",new AttributeValue().withS(colorwayID));
expressionAttributeValues.put(":productNumber",new AttributeValue().withS(productNumber));
QueryRequest queryRequest = new QueryRequest()
.withTableName(ConverseConstants.PLM_PRODUCT_TABLE)
.withKeyConditionExpression("#colorwayNumber = :colorwayNumber")
.withKeyConditionExpression("#productNumber = :productNumber")
.withExpressionAttributeNames(expressionAttributesNames)
.withExpressionAttributeValues(expressionAttributeValues);
QueryResult queryResult1 = amazonDynamoDB.query(queryRequest);
List<Map<String, AttributeValue>> results1 = queryResult1.getItems();
Following is the exception:
Caused by: com.amazonaws.services.dynamodbv2.model.AmazonDynamoDBException: Value provided in ExpressionAttributeNames unused in expressions: keys: {#colorwayNumber} (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException;
Hope I provided enough information. Thanks!
The problem seems to be here:
.withKeyConditionExpression("#colorwayNumber = :colorwayNumber")
.withKeyConditionExpression("#productNumber = :productNumber")
Here you overwrite the first expression (#colorwayNumber = :colorwayNumber) with the second one (#productNumber = :productNumber). This way, colorwayNumber is actually unused in the expressions.
I have tried the below way and its working for me.
.withKeyConditionExpression("#colorwayNumber = :colorwayNumber and #productNumber = :productNumber")
or you can try below way which should work with FilterExpression and you can build it with DynamoDBScanExpression:
.withFilterExpression(("#colorwayNumber = :colorwayNumber and #productNumber = :productNumber")
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));
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());
}
I have an XML document, that looks like this (I know, it doesn't make sense, it's just an example):
<Person>
<Name>Peter</Name>
<Country>Sweden</Country>
<Param name="Sport" value="yes"/>
<Param name="Color" value="no"/>
<Person/>
It can have an infinit number of the element Param.
Getting the content of Country I do
String country = doc.getElementsByTagName("Country").item(0).getTextContent();
Getting the content of the first attribute name of the first Param I do
String name = source.getElementsByTagName("Param").item(0).getAttributes().item(0).getNodeValue();
But how can I get all values of all the attributes of Param, without knowing how many elements of Param exist?
I need something like ("pseudo code"):
HashMap<String, String> hm = new HashMap<String, String>();
for(int i=0; i<=source.getElementsByTagName("Param").size(); i++){
String name = source.getElementsByTagName("Param").item(i).getAttributes().item(0).getNodeValue();
String value = source.getElementsByTagName("Param").item(i).getAttributes().item(1).getNodeValue();
hm.put(name, value);
}
You can ask for an attribute by its name.
String attrName = source.getElementsByTagName("Param").item(i).getAttribute("name"));
String value = source.getElementsByTagName("Param").item(i).getAttribute("value"));
//you could test if the values are null
hm.put(attrName, value);
HashMap<String, String> hm = new HashMap<String, String>();
SAXReader reader = new SAXReader();
Document document = reader.read("yourxmlfilehere(url, file)");
root = document.getRootElement();
root = root.element("Person");
for(Iterator i = root.elementIterator("Param"); i.hasNext();)
{
Element e = (Element)i.next();
hm.put(e.attributeValue("name"), e.attributeValue("value"));
}