AWS Amplify生成的listJobs查询无法获取关联客户名称
问题描述
我正在使用AWS Amplify、TypeScript和React开发一个预约系统,该系统基于「客户拥有多个作业(job)、作业拥有多个预约」的关系模型。我有一个展示作业数据库中所有作业的表格页面,希望添加一列显示该作业所属客户的名称。然而,从GraphQL schema自动生成的queries.ts中的listJobs查询仅允许获取客户ID(通过代码中的{job.clientJobsId}):
export const listJobs = /* GraphQL */ `query ListJobs($filter: ModelJobFilterInput, $limit: Int, $nextToken: String) { listJobs(filter: $filter, limit: $limit, nextToken: $nextToken) { items { id summary description jobAddress status createdBy createdAt updatedAt clientJobsId __typename } nextToken __typename } } ` as GeneratedQuery<APITypes.ListJobsQueryVariables, APITypes.ListJobsQuery>;
但运行amplify mock api并在浏览器的GraphQL explorer中,却可以创建包含客户名称的查询。我已尝试打印jobs状态对象,未发现客户名字段。现咨询:
- 为什么生成的
listJobs查询与GraphQL explorer中的不同? - 如何在表格列中显示客户名称?
解决方案
一、生成查询与GraphQL Explorer差异的原因
- Amplify自动生成的默认查询(如
listJobs)仅会获取当前模型的直接字段,不会默认关联查询关联模型的内容。这是因为自动生成的查询要兼顾通用性,避免不必要的嵌套查询造成性能浪费。 - GraphQL Explorer是基于你的schema动态生成的查询工具,允许手动选择要获取的关联字段,因此能查询到客户名称,但自动生成的代码不会默认包含这些关联内容。
二、显示客户名称的两种实现方法
方法1:自定义GraphQL查询,添加关联字段
修改自动生成的listJobs查询,或者创建新的自定义查询,在items中添加关联的客户字段(假设客户模型为Client,关联字段是client):
// 自定义带客户信息的作业查询 export const listJobsWithClient = /* GraphQL */ `query ListJobsWithClient($filter: ModelJobFilterInput, $limit: Int, $nextToken: String) { listJobs(filter: $filter, limit: $limit, nextToken: $nextToken) { items { id summary description jobAddress status createdBy createdAt updatedAt clientJobsId # 添加关联的客户字段 client { id name # 客户名称字段 __typename } __typename } nextToken __typename } } ` as GeneratedQuery<APITypes.ListJobsWithClientQueryVariables, APITypes.ListJobsWithClientQuery>;
在React组件中使用这个自定义查询替代默认的listJobs,即可从返回的job对象中通过job.client.name获取客户名称。
方法2:单独调用getClient查询获取客户信息
如果不想修改原有查询,可在获取作业列表后,对每个作业单独调用getClient查询获取客户名称:
import { API, graphqlOperation } from 'aws-amplify'; import { getClient } from './graphql/queries'; // 为作业列表添加客户名称 const fetchClientNames = async (jobs) => { return Promise.all(jobs.map(async (job) => { const clientData = await API.graphql(graphqlOperation(getClient, { id: job.clientJobsId })); return { ...job, clientName: clientData.data.getClient.name }; })); }; // 在组件中调用该函数,得到带客户名称的作业列表 const jobsWithClientNames = await fetchClientNames(jobs);
之后在表格中使用job.clientName即可显示客户名称。
注意:方法2会产生与作业数量相等的查询请求,若作业数量较多,建议优先使用方法1的嵌套查询,减少网络请求开销。
内容的提问来源于stack exchange,提问作者M455
相关产品推荐
相关产品推荐

