Dynamodb query using FilterExpression involving nested attributes with boto3

Question:

I have below data in my dynamodb table with name as partition-key.

{
    "name":"some-name",
    "age": 30,
    "addresses":[
        "addr-1",
        "addr-2"
    ],
    "status":"active"
}

I have a GSI defined with partition-key on status field.

Now, I have to run a query which returns all records whose status is active and whose address list contains a given address.

   kwargs = {
        'IndexName': 'status-index',
        'KeyConditionExpression': Key('status').eq('active'),
        'FilterExpression': 'contains(#filter, :val)',
        'ExpressionAttributeNames': {
            '#filter': 'addresses'
        },
        'ExpressionAttributeValues': {
            ':val': addr
        }
    }
    response = table.query(**kwargs)

Here, addr is the parameter passes to the function.

All this works great. But when I change the record format in the table to below, the query stops working.

updated-record-format

(addresses are now nested one level inside – in home key)

{
    "name":"some-name",
    "age": 30,
    "addresses":{
        "home":[
            "addr-1",
            "addr-2"
        ]
    },
    "status":"active"
}

updated-query

kwargs = {
            'IndexName': 'status-index',
            'KeyConditionExpression': Key('status').eq('active'),
            'FilterExpression': 'contains(#filter, :val)',
            'ExpressionAttributeNames': {
                '#filter': 'addresses.home' #nested home key on addresses
            },
            'ExpressionAttributeValues': {
                ':val': addr
            }
        }
        response = table.query(**kwargs)

How should I change the query in order to use nested list ?

Asked By: Naxi

||

Answers:

You’ve created a string called "addresses.home", which is not a pointer to a nested attribute. Use these args:

kwargs = {
            'IndexName': 'status-index',
            'KeyConditionExpression': Key('status').eq('active'),
            'FilterExpression': 'contains(#add.#hom, :val)',
            'ExpressionAttributeNames': {
                '#add': 'addresses',
                '#hom': 'home'
            },
            'ExpressionAttributeValues': {
                ':val': addr
            }
        }
Answered By: Lee Hannigan