当列更改数据库中的名称时,如何扩展或更新解析器以允许向后兼容

Posted

技术标签:

【中文标题】当列更改数据库中的名称时,如何扩展或更新解析器以允许向后兼容【英文标题】:How to extend or update a resolver to allow backwards compatibility when a column changed a name in a database 【发布时间】:2021-01-04 07:44:15 【问题描述】:

我正在开发一个使用 Node、GraphQL 和 PostgreSQL 的项目。 我有这种情况,我的数据库中有一个列需要更改为新名称,因为范围从contact 更改为contact_hours

我的问题是我必须保持向后兼容性,这意味着我一直在使用preferredContact,而新字段是preferredContactHours。为避免错过服务,我们需要确保无论何时使用preferredContact,它都会命中preferredContactHours,因此数据将一如既往地显示。

我在 DB 中进行了更改,并在我的 GQL 文件中克隆了该类型,如下所示:

type Candidate 
  id: ID!
  name: String
  contacts: [Contact]
  "Deprecated: Use the new preferredContactHours"
  preferredContact: String 
  "New naming: The hours the candidate prefers to be contacted"
  preferredContactHours: String
  

在我的 resolver.js 中,我在突变脚本下做了同样的事情:

setCandidateContactDetails(
      _,
      
        input: 
          candidateId,
          // Deprecated: Use the new preferredContactHours
          preferredContact,
          // New naming: The hours the candidate prefers to be contacted
          preferredContactHours,
          ...
      ,
      ctx
    ) 
      return CandidateService(ctx).updateCandidate(
        candidate: 
          id: candidateId,
          // Deprecated: Use the new preferredContactHours
          preferredContact,
          // New naming: The hours the candidate prefers to be contacted
          preferredContactHours,
          ...
      );

现在我需要在 Candidates 的变异中进行更改,以确保在实际使用 preferredContact 时过滤 preferredContactHours

这部分我有一个问题,因为我是 GraphQL 的新手,我不知道如何去做。 我现在的具体突变如下:

Candidate: 
    comments(candidate, _, ctx) 
      return CommentService(ctx).getComments(
        filter:  candidateId: candidate.id ,
      );
    ,

    status(candidate, args, ctx) 
      return StatusService(ctx).getCandidateStatus(candidate.id);
    ,
    activities(candidate, args, ctx) 
      return CandidateActivityService(ctx).getActivity(
        id: candidate.id,
        actions: args.actions,
      );
    ,
    contacts(candidate, args, ctx) 
      return ContactService(ctx).getContacts(
        filter: 
          candidateId: candidate.id,
        ,
      );
    ,
    nextCall(candidate, args, ctx) 
      return ScheduleService(ctx).getNextSchedule(
        candidateId: candidate.id,
        type: 'CALL',
      );
    ,
    nextVisit(candidate, args, ctx) 
      return ScheduleService(ctx).getNextSchedule(
        candidateId: candidate.id,
        type: 'VISIT',
      );
    ,
    allowedStatusChanges(candidate, args, ctx) 
      return StatusService(ctx).getAllowedStatusChanges(
        id: candidate.id,
        rule: 'allowed',
      );
    ,
    rejectionStatus(candidate, args, ctx) 
      return StatusService(ctx).getAllowedStatusChanges(
        id: candidate.id,
        rule: 'rejection',
      );
    ,
    notes(candidate, args, ctx) 
      return NoteService(ctx).getNotes(
        candidateId: candidate.id,
        questionnaireId: args.questionnaireId,
      );
    ,
    allowedActions(candidate, args, ctx) 
      return StatusService(ctx)
        .getCandidateStatus(candidate.id)
        .then(status => statusAllowedActions[status.type]);
    ,
  ,

我得到了一个建议,以在上面的 sn-p 中创建一个新条目为例

contactsHours(candidate) 
      return ContactService().getContacts(
        <Something here ???>
      );
    ,

但我不知道在这种情况下我应该怎么做,因为我对 GQL 的了解有限。

当某人希望将候选人信息作为示例显示时的预期查询

    Query
     
      candidate(id: "000") 
        name
        preferredContact
      
    
result
"data": 
    "candidate": 
      "name": "xxxx",
      "preferredContactHours": "8-12",
    
  ,

我也可以在上面的查询中用preferredContactHours 替换并得到相同的数据结果。

如果需要更多解释或代码,请评论请求,我将更新帖子以便更好地理解。

【问题讨论】:

【参考方案1】:

“已弃用”表示仍然有效,新选项与现有选项并行工作,保留所有功能。

查询这两个值应该是有效的; 两者都应该单独工作,包括过滤; 您可以在写入时将旧输入值复制到新输入值中(如果未提供新输入值); 如果没有值(旧记录),您可以读取/提供旧 DB 字段值作为新字段的结果;

返回 preferredContactHours 而不是查询的 preferredContact 在 graphql 中无效 - 服务器不应该以这种方式工作,它必须返回所有查询属性的值。

【讨论】:

好的,你不能用我的场景的可能解决方案来更新你的答案,这将是很好的获得更多信息 抱歉,今天没时间...在传递给数据库/服务之前添加一些条件/准备参数/输入值,或者在从解析器返回之前更新从数据库/服务获取的数据...您可以还尝试更新服务/中间件中的写入/读取数据(几乎不涉及解析器)......取决于实现细节【参考方案2】:

如果您运行 Postgres 12,则有一种解决方法。Postgres 12 提供了生成的列,因此您可以将新列名添加为现有的“别名”。基本上

alter table ta add column 
      preferredContactHours datatype 
      generated always as (preferredContact) stored;

其中datayype对应preferredContact的数据类型。现在您可以通过任一名称访问数据值。随着此版本的发布,您的发行说明应指出:

“preferredContact 已被优先弃用,优先于preferredContactHours 并将在版本号或日期中删除届时任何未更新为访问preferredContactHours 的应用程序都将失败”。 p>

您如何在混淆层(Node、GraphQL 等)中处理此问题,抱歉,但我不知道。祝你好运。

【讨论】:

以上是关于当列更改数据库中的名称时,如何扩展或更新解析器以允许向后兼容的主要内容,如果未能解决你的问题,请参考以下文章

当列值更改时,如何将组号添加到 SQL Server 2012 中的顺序记录?

ORA-00904: 无效的标识符,当列标题正确时

当列字段达到0时触发删除行?

当列具有返回 React 组件的 cellRenderer 时,AgGridReact rowData 更改时出错

当列和行与平面文件不匹配时,如何解决(使用)ETL

如何在集合中更改时知道在firestore中?