Wednesday 17 May 2017

AWS : It can be used scan(), query() in Lambda with DynamoDB?

I'm newbie using AWS Lambda & DynamoDB & API Gateway & IAM Role..

I'm so confisuing if the functions scan() and query() are able to be used in Lambda & node.js.

The reason why I want to use scan() and query() is to query with non-primary partition key.

I know that getItem() does work well and getItem can search with only primary partition key.

As you guys see lambda function below, I tried about 3 cases to get what I want to.

I searched lot of AWS Documentation and googled but nothing matched it made me more confused...

First, let me show Lambda function.

'use strict';

console.log('updateWordStatus : Loading function');

const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();

var AWS = require("aws-sdk");
var awsdb = new AWS.DynamoDB();

exports.handler = (event, context, callback) => {
    console.log("\nRequest received:\n", JSON.stringify(event));
    console.log("\nContext received:\n", JSON.stringify(context));

    var datetime = new Date().toString();
    const Table = {
        DICTIONARY: 'DICTIONARY_TB'
    };
    var user_id = event.params.path.user_id;

    // Get user's data
    // Case 0 : scan() - returns 'null'
    var params={
        TableName: Table.USER_WORDS,
        ProjectionExpression: "id",  //specifies the attributes you want in the scan result.
        FilterExpression: "id in :value",
        ExpressionAttributeValues: {
            ":value": user_id
        }
    };
    awsdb.scan(params, pfunc);


    // Case 1 : query() - all attempts return 'null'
    const params = {};
    params.TableName = Table.DICTIONARY;
        // attempt 1 : failed
        params.IndexName = "word";
        params.KeyConditions = [
            dynamo.Condition("id", "NOT_NULL"),
            dynamo.Condition("word", "EQ", word)
        ];
        // or attempt 2 : failed
        params.QueryFilter = dynamo.Condition("id", "EQ", user_id);
    dynamo.query(params, pfunc);

    // Basic Callback
    var pfunc = function(err, data) {
        console.log('[data]\n', data);
        if(err) {
            console.log('[errorrrrrr]\n', err);
            errorResponse();
        }
        console.log('[data]\n', data);
        var response = data.Item.id;
        callback(null, JSON.stringify(data));
    }

    console.log('[params]:\n', params);

    // case 2 : getItem - does work. returns '"{\"Item\":{\"id\":\"ObjectId(5917776622abfa3fa0711811)\",
        // \"published_date\":\"2017-05-13T21:15:18.122Z\",\"word\":\"biochemical\",
        // \"desc\":\"생화학의, 생화학적인. (또는 biochemic)\"}}"'
    const params = {
        TableName: Table.DICTIONARY,
        Key: {
            id: user_id
        },
        // attempt failed : UnexpectedParameter: Unexpected key 'KeyConditionExpression' & 'ExpressionAttributeValues' found in params
        // "KeyConditionExpression": "id = :str",
        // "ExpressionAttributeValues": {":str": user_id}
    };
    dynamo.getItem(params, (err, data) => {
        if(err) {
            console.log('[errorrrrrr]\n'+data);
            console.log('error is : ' + err);
            errorResponse();
        }
        console.log('[data]');
        console.log(data);
        var response = data.Item.id;
        callback(null, JSON.stringify(data));
    });

}

Second, Table that I want to query.

* Table name : DICTIONARY_TB
* Primary partition key : id(String)
* Items :
{
    "desc": "생화학의, 생화학적인. (또는 biochemic)",
    "id": "ObjectId(5917776622abfa3fa0711811)",
    "published_date": "2017-05-13T21:15:18.122Z",
    "word": "biochemical"
},
{
    "desc": "= DYBBUK",
    "id": "ObjectId(5917777122abfa3fa071b594)",
    "published_date": "2017-05-13T21:15:29.532Z",
    "word": "dibbuks"
},
...

Third, IAM Roles.

* Policy Name1 : AWSLambdaDynamoDocPlusQuery(custom created)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowLambdaFunctionInvocation",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction",
                "lambda:*"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "AllAPIAccessForDynamoDBStreams",
            "Effect": "Allow",
            "Action": [
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:Query",
                "dynamodb:Scan",
                "dynamodb:UpdateItem"
            ],
            "Resource": "*"
        }
    ]
}

* Policy Name2 : AWSLambdaBasicExecutionRole-fb915f1d-c3e5-41bd-b23c-99ad76d6dfac
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-2:804067700506:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-2:804067700506:log-group:/aws/lambda/updateWordStatus:*"
            ]
        }
    ]
}

I want to get some advice

  • can I use scan() and query() in Lambda?
  • to query with non-primary partition key is available in Lambda & node.js??


via geoseong

No comments:

Post a Comment