Home > Enterprise >  DynamoDB: FilterExpression when querying List Type Attribute for "Contains"
DynamoDB: FilterExpression when querying List Type Attribute for "Contains"

Time:05-18

I have looked all over the place and I can only find minimal documentation and examples on using FilterExpressions to filter records with a given value contained in a List Attribute. Almost all the other resources I was able to find were just about filtering a non list type against a list of potential matches. This AWS comparison operator function reference only mentions that the target can be a Set type, but I do see in the Condition API reference it says contains is supported for list, and the only caveat is that for (a contains b) a can be a list, but b cant. This is also noted in this post, which has the only code example I've been able to find. I tried this myself, but I'm not able to get it to work. Even where I know the item I'm searching for is contained in the list, it just succeed with an empty response.

For example, for the situation below, if I make this same request for the partition/sort key conditions with no filter- I get a successful response with correct output based on my known data. I then run the same query, trying to filter only records that contain "ENTITY123" (which I know should have matches based on the output without the filter). According to the documentation it seems like this should work as it uses contains on a List type, and checks for a non-list type (String).

code setting up the filter expression (filterExpressions is a list of strings that gets turned into the filter expression string- in this case this is the only expression as reflected in the log below):

attributeNames.put("#entities", "entities");
attributeValues.put(":entities", new AttributeValue().withS("ENTITY123"));
filterExpressions.add("contains(:entities, #entities)");

Output logging shows the expression being created correctly (also I know this approach should be working in general as I have several other attributes that can appear in the filter expression, and they all work perfectly, so the logging should reflect what's actually going into the query:

14 May 2022 00:32:14,303 [INFO] Creating query with hash key value: USER123#US
14 May 2022 00:32:14,303 [INFO] Adding range key condition: {AttributeValueList: [{S: 2021-01-01T00:00:00Z,}],ComparisonOperator: GT}
14 May 2022 00:32:14,303 [INFO] Added FilterExpression: contains(:entities, #entities)
14 May 2022 00:32:14,303 [INFO] Added Attribute Names: {#entities=entities}
14 May 2022 00:32:14,303 [INFO] Added Attribute Values: {:entities={S: ENTITY123,}}

At first I thought it might be related to the comma at the end of the attribute value in Attribute Values: {:entities={S: ENTITY123,}} but that seems to always be there, even in my other working filter expressions. Here's an example of what the actual DDB json looks like for this attribute in one of my records:

  "entities": {
    "L": [
      {
        "S": "ENTITY123"
      },
      {
        "S": "ENTITY345"
      }
    ]
  }

Can anyone point me to more concrete documentation or examples around querying/filtering against DDB List type? Does this look like it should work, or is there something I'm missing here? Thanks!

CodePudding user response:

Swap the elements in your contains function. The "name" (path) comes before the "value" (operand):

filterExpressions.add("contains(#entities, :entities)");

You are right that the filter expression docs say that contains operates on sets and strings. However, I can confirm that a contains filter expression returns the expected result when applied to a list.

  • Related