当列更改数据库中的名称时,如何扩展或更新解析器以允许向后兼容
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 中的顺序记录?