简体   繁体   中英

DynamoDB Nodejs - Query a column with array of strings

I have two columns genres and artists (both are arrays of strings) in a table in DynamoDB. A lambda function is written to get data from this table. The inputs to this lambda function are genres (array of strings - which is a subset of values in genres column) and artists (array of strings which is a subset of values in artists column).

Now i am trying to construct a query with FilterExpression that returns all columns that has at-least one of the values in genres column from genres input array or artists column from artists input array. Basically any match of atleast one string from both arrays in the respective columns.

This is what i have tried

 if (genres != null) {
            
            var genreArray = genres.split(",");

            var genresKeyObject = {};

            genreArray.forEach(function(value) {
                index++;
                var genreKey = ":genreValue" + index;
                expression_attributes[genreKey.toString()] = value;
                genresKeyObject[genreKey.toString()] = value;
            });

            filter_expression = filter_expression + " genres IN (" + Object.keys(genresKeyObject).toString() + ")";
        }


Here is an example of my FilterExpression and ExpressionAttributes values:

var params = {
            TableName: dynamodbTableName,
            IndexName: 'MonthYearIndex',
            KeyConditionExpression: "month_year = :month_year",
            FilterExpression: filter_expression,
            ExpressionAttributeValues: expression_attributes
        };

filter_expression : (artists IN (:artistValue1) OR genres IN (:genreValue2)) AND host_publisher_id = :host_pid
expression_attributes: {
    ":month_year": "2020-09",
    ":host_pid": "21",
    ":artistValue1": "Midwestern rockers",
    ":genreValue2": "Rock and Pop"
}


const data = await docClient.query(params).promise();

The above query is returning only 1 record, where as i can see that there are multiple records in db for this FilterExpression. I am trying to get all the records that match this query.

在此处输入图片说明

Basically i should be using "Contains" instead of "IN"

Here is how i constructed the filterexpression and expressionattributevalues

 var filter_expression = "";
        var expression_attributes = { ":month_year": month_year, ":host_pid": publisher_id };

        var index = 0;

        if (tags) {

            filter_expression = filter_expression + "(";

            var tagArray = tags.split(",");

            tagArray.forEach(function(value) {
                index++;
                var tagKey = ":tagValue" + index;
                expression_attributes[tagKey.toString()] = value;
                filter_expression = filter_expression + "contains (tags, " + tagKey + ") OR ";
            });

            filter_expression = filter_expression.trim();
            if (filter_expression.endsWith("OR")) {
                filter_expression = filter_expression.substring(0, filter_expression.length - 2).trim();
            }

            filter_expression = filter_expression + ")";
            filter_expression = filter_expression + " AND ";
        }

        if (DEBUG)
            console.log("FilterExpression after Tags : " + filter_expression);



        if (artists) {

            filter_expression = filter_expression + "(";

            var artistArray = artists.split(",");

            artistArray.forEach(function(value) {
                index++;
                var artistKey = ":artistValue" + index;
                expression_attributes[artistKey.toString()] = value;
                filter_expression = filter_expression + "contains (artists, " + artistKey + ") OR ";
            });

            filter_expression = filter_expression.trim();
            if (filter_expression.endsWith("OR")) {
                filter_expression = filter_expression.substring(0, filter_expression.length - 2).trim();
            }

            filter_expression = filter_expression + ")";
            filter_expression = filter_expression + " AND ";
        }

        if (DEBUG)
            console.log("FilterExpression after Artists : " + filter_expression);



        if (genres) {

            filter_expression = filter_expression + "(";

            var genreArray = genres.split(",");

            genreArray.forEach(function(value) {
                index++;
                var genreKey = ":genreValue" + index;
                expression_attributes[genreKey.toString()] = value;
                filter_expression = filter_expression + "contains (genres, " + genreKey + ") OR ";
            });

            filter_expression = filter_expression.trim();
            if (filter_expression.endsWith("OR")) {
                filter_expression = filter_expression.substring(0, filter_expression.length - 2).trim();
            }

            filter_expression = filter_expression + ")";
        }

        if (DEBUG)
            console.log("FilterExpression after Genres : " + filter_expression);

        filter_expression = filter_expression.trim();
        if (filter_expression.endsWith(" AND")) {
            filter_expression = filter_expression.substring(0, filter_expression.length - 3).trim();
        }

        if (filter_expression == "")
            filter_expression = "host_publisher_id = :host_pid";
        else
            filter_expression = filter_expression + " AND host_publisher_id = :host_pid";

        if (DEBUG) {
            console.log("Final FilterExpression : " + filter_expression);
            console.log("Final ExpressionAttributes: " + JSON.stringify(expression_attributes));
        }
        

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM