amazon-dynamodbdynamodb-queriesdynamoose

Can't scan on DynamoDB map nested attributes


I'm new to DynamoDB and I'm trying to query a table from javascript using the Dynamoose library. I have a table with a primary partition key of type String called "id" which is basically a long string with a user id. I have a second column in the table called "attributes" which is a DynamoDB map and is used to store arbitrary user attributes (I can't change the schema as this is how a predefined persistence adapter works and I'm stuck working with it for convenience). This is an example of a record in the table:

Item{2}
  attributes Map{2}
      10 Number:    2
      11 Number:    4
      12 Number:    6
      13 Number:    8
  id String: YVVVNIL5CB5WXITFTV3JFUBO2IP2C33BY

The numeric fields, such as the "12" field, in the Map can be interpreted as "week10", "week11","week12" and "week13" and the numeric values 2,4,6 and 8 are the number of times the application was launched that week.

What I need to do is get all user ids of the records that have more than 4 launches in a specific week (eg week 12) and I also need to get the list of user ids with a sum of 20 launches in a range of four weeks (eg. from week 10 to 13).

With Dynamoose I have to use the following model:

dynamoose.model(
    DYNAMO_DB_TABLE_NAME, 
    {id: String, attributes: Map},
    {useDocumentTypes: true, saveUnknown: true}
);

(to match the table structure generated by the persistence adapter I'm using). I assume I will need to do DynamoDB "scan" to achieve this rather than a "query" and I tried this to get started and get a records where week 12 equals 6 to no avail (I get an empty set as result):

const filter = {
        FilterExpression: 'contains(#attributes, :val)',
        ExpressionAttributeNames: {
          '#attributes': 'attributes',
        },
        ExpressionAttributeValues: {
          ':val': {'12': 6},
        },
      };

    model.scan(filter).all().exec(function (err, result, lastKey) {
        console.log('query result: '+ JSON.stringify(result));
    });

If you don't know Dynamoose but can help with solving this via the AWS SDK tu run a DynamoDB scan directly that might also be helpful for me.

Thanks!!


Solution

  • Try the following.

    const filter = {
        FilterExpression: '#attributes.#12 = :val',
        ExpressionAttributeNames: {
            '#attributes': 'attributes',
            '#12': '12'
        },
        ExpressionAttributeValues: {
            ':val': 6,
        },
    };
    

    Sounds like what you are really trying to do is filter the items where attributes.12 = 6. Which is what the query above will do.

    Contains can't be used for objects or arrays.