【问题标题】:aws - how to set lambda function to make dynamic query to dynamodbaws - 如何设置 lambda 函数以对 dynamodb 进行动态查询
【发布时间】:2020-11-19 12:52:40
【问题描述】:

这是我当前的 lambda 函数,它返回表“横幅”中的所有数据。

getBanner.js

'use strict'
const AWS = require('aws-sdk');

exports.handler = async function (event, context, callback) {
    const documentClient = new AWS.DynamoDB.DocumentClient();

    let responseBody = "";
    let statusCode = 0;

    const params = {
        TableName : "Banner",
    };

    try{
        const data = await documentClient.scan(params).promise();
        responseBody = JSON.stringify(data.Items);
        statusCode = 200
    }catch(err){
        responseBody = `Unable to get products: ${err}`;
        statusCode = 403
    }

    const response = {
        statusCode: statusCode,
        headers:{
            "Content-Type": "application/json",
            'Access-Control-Allow-Origin': '*', // Required for CORS support to work
        },
        body: responseBody
    }

    return response
}

是样本返回数据

[
   {
       Order: 123,
       Year: 2000
       ...
   },
   {
       Order: 77,
       Year: 2007
       ...
   }
]

我明白了如果我想查询属性顺序,我需要改为following。

...
var params = {
    TableName : "Banner",
    KeyConditionExpression: "#od = :yyyy",
    ExpressionAttributeNames:{
        "#od": "order"
    },
    ExpressionAttributeValues: {
        ":yyyy": 1
    }
};
...

如果我想执行以下操作怎么办?
可能有一些用例让我需要查询另一个属性或多个属性。

我应该如何拥有一个可以动态处理 queryStringParameters 的函数?

根据评论更新,但又出现错误

'use strict'
const AWS = require('aws-sdk');

exports.handler = async function (event, context, callback) {
    const documentClient = new AWS.DynamoDB.DocumentClient();

    let responseBody = "";
    let statusCode = 0;

    console.log(event)
    const queryStringParams = event.queryStringParameters;

    console.log(queryStringParams)

    let KeyConditionExpression = ''
    let ExpressionAttributeNames={};
    let ExpressionAttributeValues = {};
    for (const property in queryStringParams) {
      KeyConditionExpression += ` #${property} = :${property} ,`;
      ExpressionAttributeNames['#'+property] = property ;
      ExpressionAttributeValues[':'+property]=queryStringParams[property];
    }

    KeyConditionExpression= KeyConditionExpression.slice(0, -1);

    const params = {
        TableName : "Banner",
        KeyConditionExpression: KeyConditionExpression,
        ExpressionAttributeNames: ExpressionAttributeNames,
        ExpressionAttributeValues: ExpressionAttributeValues
    };

    console.log(params)   //Response A

    try{
        const data = await documentClient.scan(params).promise();
        responseBody = JSON.stringify(data.Items);
        statusCode = 200
    }catch(err){
        responseBody = `Unabel to get products: ${err}`;
        statusCode = 403
    }

    const response = {
        statusCode: statusCode,
        headers:{
            "Content-Type": "application/json",
            'Access-Control-Allow-Origin': '*', // Required for CORS support to work
        },
        body: responseBody
    }

    return response
}
Unabel to get products: ValidationException: ExpressionAttributeNames can only be specified when using expressions

这是从 cloudwatch 获得的‘params’的值 回应A

{
  TableName: 'Banner',
  KeyConditionExpression: ' #order = :order , #year = :year ',
  ExpressionAttributeNames: { '#order': 'order', '#year': 'year' },
  ExpressionAttributeValues: { ':order': '1', ':year': '2007' }
}

【问题讨论】:

    标签: node.js amazon-web-services aws-lambda amazon-dynamodb


    【解决方案1】:

    简单示例

    const getParams = (key, value) => ({
      TableName: "Banner",
      KeyConditionExpression: "#key = :value",
      ExpressionAttributeNames: {
        "#key": key
      },
      ExpressionAttributeValues: {
        ":value": value
      }
    });
    

    并根据您的查询参数调用此函数。 可以从事件中获取的查询参数。

    const queryParams = event.queryStringParameters;
    

    【讨论】:

    • 如果我有多个 queryParams 怎么办?例如 (year, order , name)
    • 您应该在 dynamoDB 中有一个索引并为其使用 KeyConditionExpression。对于多个参数,您应该使用 FilterExpression。 KeyConditionExpression 仅适用于索引主键和排序键中的键。
    【解决方案2】:

    您可以从您的 Lambda 函数处理程序中的事件对象中查询参数。事件对象内容取决于调用 Lambda 函数的服务。如果从 Elastic Load Balancing 或 API 网关调用 Lambda 函数,您可以从事件对象中获取查询参数。事件对象将有一个名为queryStringParameters 的属性,其中包含请求中的所有查询字符串参数。

    这是文档中事件对象的示例:

    {
        "requestContext": {
            "elb": {
                "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
            }
        },
        "httpMethod": "GET",
        "path": "/lambda",
        "queryStringParameters": {
            "query": "1234ABCD"
        },
        "headers": {
            "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
            "accept-encoding": "gzip",
            "accept-language": "en-US,en;q=0.9",
            "connection": "keep-alive",
            "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com",
            "upgrade-insecure-requests": "1",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
            "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476",
            "x-forwarded-for": "72.12.164.125",
            "x-forwarded-port": "80",
            "x-forwarded-proto": "http",
            "x-imforwards": "20"
        },
        "body": "",
        "isBase64Encoded": false
    }
    

    https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html https://docs.aws.amazon.com/lambda/latest/dg/lambda-services.html

    您的案例示例:(注意:查询字符串的名称必须与表达式属性相同)

    const queryStringParams = event.queryStringParams;
    const updatedQueryStringParams = {};
    
    Object.keys(queryStringParams).forEach(key => updatedQueryStringParams[`:${key}`] = queryStringParams[key]);
    
        var params = {
            TableName : "Banner",
            KeyConditionExpression: "#od = :year",
            ExpressionAttributeNames:{
                "#od": "order"
            },
            ExpressionAttributeValues: {
                ...updatedQueryStringParams
            }
        };
    

    【讨论】:

    • 你能给出一些示例代码来展示如何动态使用 queryStringParameters 吗?
    • const { order, year } = event.queryStringParameters; var params = { TableName : "Banner", KeyConditionExpression: "#od = :yyyy", ExpressionAttributeNames:{ "#od": "order" }, ExpressionAttributeValues: { ":yyyy": year } };
    • 有动态的方法吗?因为我可能会使用更多或更少的属性进行查询
    • 是的,您可以在 event.queryStringParameters 中循环键并在每个键的名称前添加冒号,然后用户扩展运算符将键和值分配给 ExpressionAttributeValues。但这伴随着安全代价。我将在上面的答案中为您提供示例。
    • 谢谢。但是为什么这会带来安全价格呢?
    【解决方案3】:

    在使用扫描而不是 KeyConditionExpression 时使用 FilterExpression。 样本

    const queryStringParams = event.queryStringParameters;
      let FilterExpression = "";
      let ExpressionAttributeNames = {};
      let ExpressionAttributeValues = {};
      for (const property in queryStringParams) {
        FilterExpression += ` #${property} = :${property} ,`;
        ExpressionAttributeNames["#" + property] = property;
        ExpressionAttributeValues[":" + property] = queryStringParams[property];
      }
    
      FilterExpression = FilterExpression.slice(0, -1);
      
    
      const params = {
        TableName: tableName,
        FilterExpression: FilterExpression,
        ExpressionAttributeNames: ExpressionAttributeNames,
        ExpressionAttributeValues: ExpressionAttributeValues
      };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-17
      • 2020-02-11
      • 2021-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多