Scaramouche
Scaramouche

Reputation: 3267

DynamoDB in Node.js SDK - Scan and filter without specific array index

I'm writing a simple scan operation in an AWS lambda for a DynamoDB table.

Each element of the table has properties city (string) and lines (array). Each line has a line_id.

Example record:

"city": "Sin",
"lines": [
    {
        "line_id": 111,
    },
    {
        "line_id": 4,
    }
]

I've been reading about using FilterExpression on a nested attribute, in this case line_id.

As I understand, in this article for example, under Nested query (sorry, no permalink), we can use something like this:

const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { ScanCommand } = require('@aws-sdk/lib-dynamodb');

const ddbClient = new DynamoDBClient({ region: 'region' });

const command = new ScanCommand({
    TableName: 'tableName',
    ProjectionExpression: 'city, lines',
    ExpressionAttributeNames: {
      '#line_id': 'line_id'
    },
    ExpressionAttributeValues: {
      ':idd': 4
    },
    FilterExpression: 'lines.#line_id = :idd',
});

ddbClient.send(command);

in order to find records that contain at least one line with line_id equal to 4.

I'm receiving an empty result.

Is this approach plausible, or did I misunderstand the explanation?

Can this actually be done in DynamoDB, or do I have to do this in the code after I receive the entire scan result?

PS: found this SO post which also suggests something similar, but I just can't make it work.

Upvotes: 0

Views: 1227

Answers (1)

fedonev
fedonev

Reputation: 25799

lines is a list, not an object. You can use bracket indexing (lines[0]), but not dot-syntax (lines.#line_id) on a list.

Your scan will work if you refactor lines to be an object with line_id as the key and an list of line_id records as values.

"lines": {
  111: [{ "line_id": 111}],
  4: [{ "line_id": 4}],
}

If that's not possible or worthwhile, you are stuck with a client-side or lambda-side transformation.

Upvotes: 1

Related Questions