DynamoDB: How to use a query filter to check for conditions in a MAP

37,141

Try comparing the map attribute data.byUserId instead of the entire map structure:

Table table = dynamoDB.getTable(tableName);

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":x", "vl49uga5ljjcoln65rcaspmg8u");


QuerySpec spec = new QuerySpec()
    .withHashKey("HashKeyAttribute", "HashKeyAttributeValue")
    .withFilterExpression("data.byUserId = :x")
    .withValueMap(expressionAttributeValues);


ItemCollection<QueryOutcome> items = table.query(spec);

Iterator<Item> iterator = items.iterator();

while (iterator.hasNext()) {
    System.out.println(iterator.next().toJSONPretty());
}

Some important guidelines:

  1. Make sure the variable tableName has the correct table name represented as a string.

  2. Make sure to replace the string HashKeyAttribute with the attribute name that represents your Hash Key.

  3. Make sure to replace the string HashKeyAttributeValue with the value that represents the Hash Key that you want to match.

  4. Make sure the matched record has the data.byUserId with the value provided in the comparison expression. In the example the value "vl49uga5ljjcoln65rcaspmg8u" was provided.

Here is another example having the id attribute as the Hash Key:

Table table = dynamoDB.getTable(tableName);

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":x", "vl49uga5ljjcoln65rcaspmg8u");


QuerySpec spec = new QuerySpec()
    .withHashKey("id", "25g77vmummpr4mc5mb9vq36q43")
    .withFilterExpression("data.byUserId = :x")
    .withValueMap(expressionAttributeValues);


ItemCollection<QueryOutcome> items = table.query(spec);

Iterator<Item> iterator = items.iterator();

while (iterator.hasNext()) {
    System.out.println(iterator.next().toJSONPretty());
}
Share:
37,141
ThePedestrian
Author by

ThePedestrian

Updated on July 27, 2022

Comments

  • ThePedestrian
    ThePedestrian almost 2 years

    I have a table and the structure looks like this:

    DynamoDB document

    When I do a query, I would like to be able to do a query filter on the data map; but I'm not exactly sure how to setup the query.

    This is what I have so far:

    HashMap<String, AttributeValue> map = new HashMap<String, AttributeValue>();
    map.put("byUserId", new AttributeValue().withS("vl49uga5ljjcoln65rcaspmg8u"));
    
    queryExpression
        .withQueryFilterEntry("data", new Condition()
            .withAttributeValueList(new AttributeValue().withM(map))
            .withComparisonOperator(ComparisonOperator.CONTAINS));
    

    but the way I'm building the filter is not correct and I keep running into the following error:

    Exception in thread "main" com.amazonaws.AmazonServiceException: One or more parameter values were invalid: ComparisonOperator CONTAINS is not valid for M AttributeValue type (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: CHIOME68L1HVGO81URD7CIOS6BVV4KQNSO5AEMVJF66Q9ASUAAJG)
        at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1077)
        at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:725)
        at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:460)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:295)
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:3106)
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.query(AmazonDynamoDBClient.java:1118)
    

    So what is a comparison operator I should be using (since IN is for list types), and how do I build the query filter such that I can specify a comparison inside of the MAP.

    Thanks!

  • ThePedestrian
    ThePedestrian almost 9 years
    Thank you for your response but unfortunately it did not work. :(
  • b-s-d
    b-s-d almost 9 years
    Can you provide more details?
  • b-s-d
    b-s-d almost 9 years
    What is the end result with the provided answer? Error? No results being returned?
  • ThePedestrian
    ThePedestrian almost 9 years
    Wonderful!!! Thank you so much! This worked great. Few things I would mention for future readers is that data is a reserved keyword. Once, I changed the attribute name, I was able to use @spin code.
  • ThePedestrian
    ThePedestrian almost 9 years
    I have one more question. I'm trying to refactor my code to use the high-level API. How do I set the expression attribute values? Is it possible to do in the high-level API? You can view my code here.
  • b-s-d
    b-s-d almost 9 years
    I believe these guidelines on how to use placeholders will be helpful on this case: docs.aws.amazon.com/amazondynamodb/latest/developerguide/…
  • Kuldeep Yadav
    Kuldeep Yadav over 5 years
    Can condition be not used for nested attribute data. byUserId?