首页 > 解决方案 > 您如何将不同表中的字段值映射到 API 中的 id?

问题描述

我知道标题可能不是自我解释的,所以我会尽量清楚地提出我的问题。

我有一个 NodeJS 应用程序,需要定期将其一些内容发布到外部 API。此内容存储在 MySQL 数据库中,并分散在几个表之间。因此,假设我们有两个表(显然行数比这多得多,但你明白我的意思):

Table A:
+-------+---------+---------+---------+
|  id   | field_1 | field_2 | field_3 |
+-------+---------+---------+---------+
| uuid1 | value1  | value2  | value3  |
+-------+---------+---------+---------+

Table B:
+-------+-------------------+---------+---------+
|  id   |  id_field_A (FK)  | field_4 | field_5 |
+-------+-------------------+---------+---------+
| uuid3 |  uuid1            | value4  | value5  |
+-------+-------------------+---------+---------+

并且对于与表 BI 连接的表 A 的每一行,必须发布一个 DTO 看起来像这样的对象:

{
    "title": "value3",
    "attributes: {
        "10": "value1",
        "9": "value2",
        "1": "value4",
        "16": "value5" 
    }    
}

因此,每个 id(示例中为“1”、“9”、“10”、“16”)都用作对象中的键,attributes其值应与表 A 或 B 中的字段值相匹配。

外部 API id(“1”、“9”、“10”、“16”)不应该在不同的环境之间变化,所以我的想法是创建一个新表来将这些 id 映射到表和字段名称并获取这些数据任何时候我们需要将数据发布或更新到 API 时,都可以从我们的数据库中获取。像这样:

Table api_attribute:
+-------+-----------------+------------+-----------------+
|  id   |   table_name    | field_name | id_external_api |
+-------+-----------------+------------+-----------------+
| uuid4 |  Table A        | field_1    | "10"            |
+-------+-----------------+------------+-----------------+
| uuid5 |  Table A        | field_2    | "9"             |
+-------+-----------------+------------+-----------------+
| uuid6 |  Table B        | field_4    | "1"             |
+-------+-----------------+------------+-----------------+
| uuid7 |  Table B        | field_5    | "16"            |
+-------+-----------------+------------+-----------------+

我对开发游戏很陌生,所以我不确定这是否是推荐的解决方案,如果不是,我只是在努力寻找有关此类主题的任何文章,所以我想我错过了一些这个特殊问题的关键字在这里......

编辑:既然我已经写了所有这些,我意识到这可能有点矫枉过正,我只需要在普通的 javascript 中映射所有这些字段,因为无论如何都无法以编程方式确定 id。也许我应该使用一个简单的类来创建 DTO 并在我的 api 服务中使用它,如下所示:

>>>>>>>>>> apiDTO.class.js
class ApiDTO {
    constructor({field_1: value1, field_2: value2, ..., field_5: value5}) {
        this.title: value3;
        this.attributes = {
            "10": value1,
            "9": value2,
            "1": value4,
            "16": value5 
        };
    }
}
module.exports = ApiDTO ;

>>>>>>>> api.service.js
const ApiDTO = require('./apiDTO.class');

module.exports.createAnApiEntity = async () => {
    const allDataToSendToApi = await dataFromDService.getAllFromTableAJoinTableB();
    for (dataToSend of allDataToSendToApi) {
        const apiDto = new ApiDto(dataToSend);
        sendToApi(apiDto);
    }
}

问题是,这个解决方案意味着只有开发人员才能更改 id,因为它是硬编码的数据,如果我们要向有效负载添加字段和值,这些更改将需要一个新版本......

标签: javascriptmysqlnode.jsdatabasemodel

解决方案


假设dataToSend始终是一个平面对象,您可以将第二个片段中的 DTO 定义放入dtoTemplate.json您当前拥有的确切 JSON 格式的文件(例如)中。该文件可以在运行时由您的代码读取(您可以使用此答案或链接问题中讨论的异步方法之一),并且您可以动态匹配模板 JSON 文件中的值与dataToSend.

一个简单的实现可以是:

function convertToApiDTO(dataToSend) {
  const fs = require('fs');
  const templateJson = fs.readFileSync('path/to/dtoTemplate.json', 'utf8');
  return JSON.parse(
    templateJson,
    (dtoKey, dbKeyOrValue) => dbKeyOrValue in dataToSend ?
      dataToSend[dbKeyOrValue] :
      dbKeyOrValue
  );
}

我建议添加额外的错误处理,因为文件中包含无效的 JSON 可能会破坏此功能。此外,如果您的 JSON 文件可以被不受信任的第三方解析,那么由于原型中毒漏洞,它也可能很危险。

请注意,如果dbKeyOrValue不是 中的键dataToSend,则此函数将 设置为结果对象中dbKeyOrValue带有键的常量值。dtoKey如果您想跳过这些字段,则可以返回undefined而不是dbKeyOrValue.


推荐阅读