如何查询这个自动生成的 AWS Amplify API?

How do I query this auto generated AWS Amplify API?

我正在尝试使用邮递员查询自动生成的 Amplify API。我正在用我的头撞墙来做一些应该很简单的事情。有人可以解释为什么这个查询 URL 没有 return 一个 JSON 对象吗?数据存在于 dynamo 中,但 return 在 postman 中是一个空数组(状态为 200):

邮递员(这是我期望的工作):

https://xxxxx.execute-api.us-east-1.amazonaws.com/staging/api/getShipContainer?location=fl

UPDATE 在盯着代码看了更长时间后,我发现 req.params[partitionKeyName] 正在以某种方式评估 getShipContainer,这可以解释我的问题,但我该如何解决这个问题?为什么会这样:

condition[partitionKeyName]['AttributeValueList'] = [ convertUrlType(req.params[partitionKeyName], partitionKeyType) ];

此语法有效(returns dynamo 对象)但显然不正确(location 是一个 dynamo 列,而 fl 是过滤器参数):https://xxxxxx.execute-api.us-east-1.amazonaws.com/staging/api/fl?location

查询方法:

const userIdPresent = false; // TODO: update in case is required to use that definition
const partitionKeyName = "location";
const partitionKeyType = "S";
const sortKeyName = "containerId";
const sortKeyType = "S";
const hasSortKey = sortKeyName !== "";
const path = "/api";
const UNAUTH = 'UNAUTH';
const hashKeyPath = '/:' + partitionKeyName;
const sortKeyPath = hasSortKey ? '/:' + sortKeyName : '';
// declare a new express app
var app = express()
app.use(bodyParser.json())
app.use(awsServerlessExpressMiddleware.eventContext())

//Enable CORS for all methods
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*")
  res.header("Access-Control-Allow-Headers", "*")
  next()
});

// convert url string param to expected Type
const convertUrlType = (param, type) => {
  switch(type) {
    case "N":
      return Number.parseInt(param);
    default:
      return param;
  }
}

/********************************
 * HTTP Get method for list objects *
 ********************************/
//api/:location
app.get(path + hashKeyPath, function(req, res) {
  var condition = {}
  condition[partitionKeyName] = {
    ComparisonOperator: 'EQ'
  }

  if (userIdPresent && req.apiGateway) {
    condition[partitionKeyName]['AttributeValueList'] = [req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH ];
  } else {
    try {
      condition[partitionKeyName]['AttributeValueList'] = [ convertUrlType(req.params[partitionKeyName], partitionKeyType) ];
    } catch(err) {
      res.statusCode = 500;
      res.json({error: 'Wrong column type ' + err});
    }
  }

  let queryParams = {
    TableName: tableName,
    KeyConditions: condition
  }
  console.log(`req gg cond::`,JSON.stringify(condition),`params`,Object.entries(req.params).map(([i,k])=>i+' '+k).join(','))

  dynamodb.query(queryParams, (err, data) => {
    if (err) {
      res.statusCode = 500;
      res.json({error: 'Could not load items: ' + err});
    } else {
      res.json(data.Items);
    }
  });
});

我投入调试的 console.log 结果:

req gg cond:: 
{
    "location": {
        "ComparisonOperator": "EQ",
        "AttributeValueList": [
            "getShipContainer"
        ]
    }
}
 params location getShipContainer

预期的查询不应该使用 LOCATION 并完全忽略“getShipContainer”吗?我很困惑,因为代码是自动生成的。 getShipContainer 是被调用的 lambda 函数的名称

我也在 API 网关测试控制台中测试了这个,结果相同:

这是我的发电机 table 的快速截图:

github issue 中提到了该问题。

将您的处理函数更改为此,https://xxxxx.execute-api.us-east-1.amazonaws.com/staging/api/location 将 return 项目列表。

app.get(path + hashKeyPath, function (req, res) {
  let scanParams = {
    TableName: tableName,
  };

  dynamodb.scan(scanParams, (err, data) => {
    if (err) {
      res.statusCode = 500;
      res.json({ error: "Could not load items: " + err });
    } else {
      res.json(data.Items);
    }
  });
});

如果参数在 URL 中指定,这里是过滤代码。

位置是 dynamodb reserved word 之一,所以我使用了属性映射。

https://xxxxx.execute-api.us-east-1.amazonaws.com/staging/api/location?location=fl

app.get(path + hashKeyPath, function (req, res) {
  var filterParams = {};
  const location = req.query[partitionKeyName] || "";

  if (location) {
    filterParams = {
      FilterExpression: "#loc = :loc",
      ExpressionAttributeNames: {
        "#loc": "location",
      },
      ExpressionAttributeValues: {
        ":loc": location,
      },
    };
  }

  let scanParams = {
    TableName: tableName,
    ...filterParams,
  };

  dynamodb.scan(scanParams, (err, data) => {
    if (err) {
      res.statusCode = 500;
      res.json({ error: "Could not load items: " + err });
    } else {
      res.json(data.Items);
    }
  });
});

通常我使用DynamoDB Global Secondary Index 来查询所有项目。但这可能取决于用例。例如,我曾经通过站点 ID 查询项目列表。

Table would be something like this: 

itemID
itemName
siteID
router.get("/", function (req, res) {
  const sortKeyName = "siteID";

  let queryParams = {
    TableName: tableName,
    IndexName: "siteIDGSI",
    KeyConditionExpression: "siteID = :site_id",
    ExpressionAttributeValues: {
      ":site_id": req.params[sortKeyName],
    },
  };

  dynamodb.query(queryParams, (err, data) => {
    if (err) {
      res.statusCode = 500;
      res.json({ error: "Could not load items: " + err });
    } else {
      res.json({
        statusCode: 200,
        message: "List of Items in " + req.params[sortKeyName],
        items: data.Items,
      });
    }
  });
});

因此您可以为 containerId

创建 GSI