Apollo联邦图跨子图关联实体(Elixir/Absinthe)实现咨询
解决方案:Apollo联邦下跨子图关联查询配置
一、后端子图改造(Elixir/Absinthe)
因为是联邦架构,不能直接在ProjectLocation子图中定义Inspection类型,需要通过联邦实体扩展实现跨子图关联。
1. 标记ProjectLocation为联邦实体
修改ProjectLocation子图的类型定义,添加联邦支持并标记主键:
defmodule MyProject.Schema.Types.ProjectLocation do use Absinthe.Schema.Notation use Absinthe.Federation.Schema.Notation # 引入联邦扩展 object :project_location do @key(fields: "id") # 标记为联邦实体,主键为id field :id, :id field :project_id, :id field :address, :string end input_object :input_project_location_params do field :id, :id field :project_id, :id field :address, :string end end
2. 在Inspection子图中扩展ProjectLocation实体
Inspection子图拥有关联数据,因此在这里扩展ProjectLocation,添加带参数的inspections字段:
defmodule MyInspectionProject.Schema.Types.Inspection do use Absinthe.Schema.Notation use Absinthe.Federation.Schema.Notation # 引入联邦扩展 # 扩展ProjectLocation实体,添加关联查询字段 extends object :project_location do @key(fields: "id") field :inspections, list_of(:inspection) do arg(:status, :string) # 定义过滤参数 resolve(&MyInspectionProject.Schema.Resolvers.Inspection.get_inspections_by_location/3) end end object :inspection do field :id, :id field :project_id, :id field :inspection_location, :id # 建议重命名为project_location_id提升可读性 field :status, :string end input_object :input_inspection_params do field :id, :id field :project_id, :id field :inspection_location, :id field :status, :string end end
3. 编写Inspection关联查询解析器
添加解析函数,根据ProjectLocation ID和过滤参数查询关联数据:
defmodule MyInspectionProject.Schema.Resolvers.Inspection do # 新增:按ProjectLocation ID和status过滤查询Inspections def get_inspections_by_location(%{id: location_id}, args, _context) do # 替换为你的Ecto查询逻辑 query = from i in Inspection, where: i.inspection_location == ^location_id # 处理可选的status过滤参数 query = if args[:status], do: from i in query, where: i.status == ^args[:status], else: query {:ok, Repo.all(query)} end # 保留原有查询逻辑 def get_inspection(_parent, %{inspection: params}, _context) do # 原解析逻辑 end end
4. 配置联邦标准查询(必选)
两个子图都需要添加联邦网关要求的标准查询,确保网关能发现子图:
# 在ProjectLocation和Inspection子图的Schema文件中添加 defmodule MyProject.Schema do use Absinthe.Schema use Absinthe.Federation.Schema query do import_fields :project_location_queries # 联邦标准实体查询 field :_entities, list_of(:entity) do arg(:representations, non_null(list_of(non_null(:_any)))) resolve(&Absinthe.Federation.resolve_entities/3) end # 联邦服务元数据查询 field :_service, :_service do resolve(&Absinthe.Federation.Service.resolve/3) end end end
二、前端查询改造(React/Apollo Client)
1. 修正GraphQL查询语法
你之前的查询存在语法错误,正确写法如下(支持传入过滤变量):
const GET_PROJECT_LOCATIONS = gql` query ProjectLocations($projectId: ID!, $inspectionStatus: String) { projectLocations(projectId: $projectId) { id projectId address # 传入过滤参数,使用变量$inspectionStatus inspections(status: $inspectionStatus) { id projectId inspectionLocation # 注意:Absinthe自动将蛇形命名转为驼峰 status } } } `;
2. useLazyQuery的变量传递
调用查询时,变量对象包含必填的projectId和可选的inspectionStatus:
const [getProjectLocations, { data, loading, error }] = useLazyQuery(GET_PROJECT_LOCATIONS); // 触发查询的函数 const fetchProjectData = () => { getProjectLocations({ variables: { projectId: "你的项目ID", inspectionStatus: "待审核" // 不需要过滤时可省略该字段 } }); };
关键注意事项
- 联邦子图关联必须通过
@key标记的实体实现,网关会自动路由跨子图查询 - Absinthe默认将后端蛇形命名字段转为前端驼峰命名,查询时需对应
- 解析函数要处理可选参数的空值情况,避免查询出错
内容的提问来源于stack exchange,提问作者mac
相关产品推荐
相关产品推荐

