Skate to Eat
Skate to Eat

Reputation: 2804

How to make search using "contains" with DynamoDB

I'm trying to make search function on my React app.

I have this DynamoDB table:

---------------------
movie_id | movie_name
---------------------
1        | name a
---------------------
2        | name b
---------------------

I want to make a search function to search "b" on the React app's search input and get "name b" from the DB as the result.

I tried to query with CONTAINS but didn't work and does not seem to be a proper way to do it.

const SEARCH_KEYWORD = "b";

let params = {
   TableName : 'TABLE_NAME',
   KeyConditionExpression: "contains(#movie_name, :movie_name)",
   ExpressionAttributeNames:{
     "#movie_name": 'movie_name'
   },
   ExpressionAttributeValues:{
       ":movie_name": SEARCH_KEYWORD
   }
};
documentClient.query(params, function(err, data) {
  console.log(data);
});

What is the best way to create search function on my React app with DynamoDB?

Does it even make sense to run a query by the search keyword to check if the data contains keyword value?

Upvotes: 20

Views: 47042

Answers (2)

swapnil Bhosale
swapnil Bhosale

Reputation: 33

We can use CONTAINS operator in the query API as below.

  Map<String, AttributeValue> eav = new HashMap<String, AttributeValue>();
  Map<String, String> expression = new HashMap<>();
  expression.put("#ProductName","name");
  expression.put("#Type","type");

  eav.put(":" + Constant.QUERY_VAL, new AttributeValue().withS(productList.get(0).getId()));
  eav.put(":search", new AttributeValue().withS(productText));
  DynamoDBQueryExpression<ProductEntity> queryExpression = new DynamoDBQueryExpression<ProductEntity>()
      .withIndexName(Constant.PRODUCTSLIST_INDEX)
      .withKeyConditionExpression(Constant.PRODUCTLISTID + "=:" + Constant.QUERY_VAL)
      .withFilterExpression(
          "(contains (sku,:search)) OR (contains (brandName,:search)) OR (contains (description,:search)) OR (contains (#Type,:search)) OR (contains (#ProductName,:search))")
      .withExpressionAttributeNames(expression)
      .withExpressionAttributeValues(eav).withScanIndexForward(false).withConsistentRead(false);      
  result = dynamoDBMapper.query(ProductEntity.class, queryExpression, conf);
  

Upvotes: 1

Zanon
Zanon

Reputation: 30770

The CONTAINS operator is not available in the query API. You need to use the scan API for this (see this link).

Try the following:

const AWS = require('aws-sdk');
const documentClient = new AWS.DynamoDB.DocumentClient();
const SEARCH_KEYWORD = "b";

let params = {
    TableName : 'TABLE_NAME',
    FilterExpression: "contains(#movie_name, :movie_name)",
    ExpressionAttributeNames: {
        "#movie_name": "movie_name",
    },
    ExpressionAttributeValues: {
        ":movie_name": SEARCH_KEYWORD,
    }       
};

documentClient.scan(params, function(err, data) {
    console.log(data);
});

Result:

{ 
    Items: [ 
        { 
            movie_id: 2,
            movie_name: 'name b' 
        } 
    ], 
    Count: 1, 
    ScannedCount: 2 
}

Upvotes: 25

Related Questions