19

我正在使用Amazon Aurora Serverless 的新数据 API

是否可以在响应中获取表列名称?

例如,如果我在包含、、、、列的用户表中运行以下查询:idfirst_namelast_nameemailphone

const sqlStatement = `
    SELECT *
    FROM user
    WHERE id = :id 
`;
const params = {
    secretArn: <mySecretArn>,
    resourceArn: <myResourceArn>,
    database: <myDatabase>,
    sql: sqlStatement,
    parameters: [
        {
            name: "id",
            value: {
                "stringValue": 1
            }
        }
    ]
};
let res = await this.RDS.executeStatement(params)
console.log(res);

我收到了这样的回复,所以我需要猜测哪个列对应于每个值:

{
    "numberOfRecordsUpdated": 0,
    "records": [
        [
            {
                "longValue": 1
            },
            {
                "stringValue": "Nicolas"
            },
            {
                "stringValue": "Perez"
            },
            {
                "stringValue": "example@example.com"
            },
            {
                "isNull": true
            }
        ]
    ]
}

我想得到这样的回应:

{
    id: 1,
    first_name: "Nicolas",
    last_name: "Perez",
    email: "example@example.com",
    phone: null
}

更新1

我找到了一个封装 Aurora Serverless Data API 并简化开发的npm 模块

4

5 回答 5

10

我们决定采用当前的方法,因为我们试图减少响应大小,并且在每条记录中包含列信息是多余的。

您可以明确选择在结果中包含列元数据。请参阅参数:“includeResultMetadata”。

https://docs.aws.amazon.com/rdsdataservice/latest/APIReference/API_ExecuteStatement.html#API_ExecuteStatement_RequestSyntax

于 2019-07-31T17:56:37.773 回答
8

同意这里的共识,应该有一种开箱即用的方式来从数据服务 API 中做到这一点。因为没有,这里有一个 JavaScript 函数来解析响应。

const parseDataServiceResponse = res => {
    let columns = res.columnMetadata.map(c => c.name);
    let data = res.records.map(r => {
        let obj = {};
        r.map((v, i) => {
            obj[columns[i]] = Object.values(v)[0]
        });
        return obj
    })
    return data
}
于 2020-07-14T15:25:10.953 回答
2

我理解这种痛苦,但看起来这是合理的,因为 select 语句可以连接多个表并且可能存在重复的列名。

类似于上面来自@C.Slack 的答案,但我使用了 map 和 reduce 的组合来解析来自 Aurora Postgres 的响应。

// declarative column names in array
const columns = ['a.id', 'u.id', 'u.username', 'g.id', 'g.name'];

// execute sql statement
const params = {
  database: AWS_PROVIDER_STAGE,
  resourceArn: AWS_DATABASE_CLUSTER,
  secretArn: AWS_SECRET_STORE_ARN,
  // includeResultMetadata: true,
  sql: `
    SELECT ${columns.join()} FROM accounts a 
    FULL OUTER JOIN users u ON u.id = a.user_id
    FULL OUTER JOIN groups g ON g.id = a.group_id
    WHERE u.username=:username;
  `,
  parameters: [
    {
      name: 'username',
      value: {
        stringValue: 'rick.cha',
      },
    },
  ],
};
const rds = new AWS.RDSDataService();
const response = await rds.executeStatement(params).promise();

// parse response into json array
const data = response.records.map((record) => {
  return record.reduce((prev, val, index) => {
    return { ...prev, [columns[index]]: Object.values(val)[0] };
  }, {});
});

希望此代码段对某人有所帮助。

这是回应

[
  {
    'a.id': '8bfc547c-3c42-4203-aa2a-d0ee35996e60',
    'u.id': '01129aaf-736a-4e86-93a9-0ab3e08b3d11',
    'u.username': 'rick.cha',
    'g.id': 'ff6ebd78-a1cf-452c-91e0-ed5d0aaaa624',
    'g.name': 'valentree',
  },
  {
    'a.id': '983f2919-1b52-4544-9f58-c3de61925647',
    'u.id': '01129aaf-736a-4e86-93a9-0ab3e08b3d11',
    'u.username': 'rick.cha',
    'g.id': '2f1858b4-1468-447f-ba94-330de76de5d1',
    'g.name': 'ensightful',
  },
]
于 2020-08-30T06:29:55.450 回答
1

我已经添加到C. Slack已经提供的出色答案中,通过在 JSON 中给出响应 {"isNull": true } 来处理 AWS 处理空的可空字符字段。

这是我通过返回一个空字符串值来处理这个问题的函数——这就是我所期望的。

const parseRDSdata = (input) => {
let columns = input.columnMetadata.map(c => { return { name: c.name, typeName: c.typeName}; });

let parsedData = input.records.map(row => {
        let response = {};

        row.map((v, i) => {
                //test the typeName in the column metadata, and also the keyName in the values - we need to cater for a return value of { "isNull": true } - pflangan
                if ((columns[i].typeName == 'VARCHAR' || columns[i].typeName == 'CHAR') && Object.keys(v)[0] == 'isNull' && Object.values(v)[0] == true)
                   response[columns[i].name] = '';
                else
                  response[columns[i].name] = Object.values(v)[0];
            }
        );
        return response;
    }
);
return parsedData;

}

于 2021-04-02T13:51:41.053 回答
0

与其他答案类似,但如果您使用的是 Python/Boto3:

def parse_data_service_response(res):
    columns = [column['name'] for column in res['columnMetadata']]

    parsed_records = []
    for record in res['records']:
        parsed_record = {}
        for i, cell in enumerate(record):
            key = columns[i]
            value = list(cell.values())[0]
            parsed_record[key] = value
        parsed_records.append(parsed_record)

    return parsed_records
于 2022-02-09T14:45:06.940 回答