1

在我的 Lambda 函数中,我只想有条件地将项目放入我的 DynamoDB 中,前提是该值已经不存在。我看到了多个不同的来源,他们使用了这个 ConditionExpression,我不知道这有什么问题。

body = await dynamo.put({
                    TableName: 'polit-stream',
                    Item: {
                        urlPath: data.urlPath,
                    },
                    ConditionExpression: "attribute_not_exists(urlPath)"
                }).promise();

即使我的二级索引值 (urlPath) 已经存在,put 也将始终成功。

完整代码:

const AWS = require('aws-sdk');
const crypto = require("crypto");
const dynamo = new AWS.DynamoDB.DocumentClient();

/**
 * Demonstrates a simple HTTP endpoint using API Gateway. You have full
 * access to the request and response payload, including headers and
 * status code.
 *
 * To scan a DynamoDB table, make a GET request with the TableName as a
 * query string parameter. To put, update, or delete an item, make a POST,
 * PUT, or DELETE request respectively, passing in the payload to the
 * DynamoDB API as a JSON body.
 */
exports.handler = async(event, context) => {

    let body;
    let statusCode = '200';
    const headers = {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '* '
    }

    const data = JSON.parse(event.body);
    const generateUUID = () => crypto.randomBytes(16).toString("hex");

    try {
        switch (event.httpMethod) {
            case 'DELETE':
                body = await dynamo.delete(JSON.parse(event.body)).promise();
                break;
            case 'GET':
                body = await dynamo.scan({
                        TableName: 'db',
                        IndexName: 'urlPath',
                        FilterExpression: "urlPath = :urlPath",
                        ExpressionAttributeValues: {
                            ":urlPath": event.queryStringParameters.urlPath
                        }
                    },
                    function(data) {

                    }).promise();
                break;
            case 'POST':
                body = await dynamo.put({
                    TableName: 'db',
                    Item: {
                        id: generateUUID(),
                        name: data.name,
                        date: data.date,
                        place: data.place,
                        goals: data.goals,
                        type: data.type,
                        org: data.org,
                        email: data.email,
                        urlPath: data.urlPath,
                        createdAt: new Date().toISOString()
                    },
                    ConditionExpression: "attribute_not_exists(urlPath)"
                }).promise();
                break;
            case 'PUT':
                body = await dynamo.update(JSON.parse(event.body)).promise();
                break;
            default:
                throw new Error(`Unsupported method "${event.httpMethod}"`);
        }
    }
    catch (err) {
        statusCode = '400';
        body = err.message;
    }
    finally {
        body = JSON.stringify(body);
    }

    return {
        statusCode,
        body,
        headers,
    };
};
4

2 回答 2

3

您的错误是您误解了ConditionExpression可以做什么。您的完整PutItem代码是:

               body = await dynamo.put({
                    TableName: 'db',
                    Item: {
                        id: generateUUID(),
                        name: data.name,
                        date: data.date,
                        place: data.place,
                        goals: data.goals,
                        type: data.type,
                        org: data.org,
                        email: data.email,
                        urlPath: data.urlPath,
                        createdAt: new Date().toISOString()
                    },
                    ConditionExpression: "attribute_not_exists(urlPath)"
                }

你期望ConditionExpression: "attribute_not_exists(urlPath)"做什么?

显然您认为它会检查是否存在任何具有此值的项目urlPath。但不幸的是,这不是这个表达式的作用。它的作用是查看一个特定项目 - 具有相同密钥的项目(我不知道您的密钥是什么,id?)并检查该特定项目是否具有urlPath属性(具有任何值)。

如果urlPath是项目的钥匙,这项工作就像你希望的那样。如果urlPath是唯一的(根据您想要做的,它似乎是唯一的)那么它确实可以用作项目键。

于 2020-09-01T12:56:17.203 回答
1

为了使用 ConditionExpression,您需要为属性提供名称和值。尝试这个:

await dynamo.put({
  TableName: 'db',
  Item: {
    id: generateUUID(),
    name: data.name,
    date: data.date,
    place: data.place,
    goals: data.goals,
    type: data.type,
    org: data.org,
    email: data.email,
    urlPath: data.urlPath,
    createdAt: new Date().toISOString(),
  },
  ConditionExpression: "attribute_not_exists(#u) or (#u=:urlPath)",
  ExpressionAttributeNames: { "#u": "urlPath" },
  ExpressionAttributeValues: { ":urlPath": data.urlPath },
});
于 2020-09-01T09:46:56.900 回答