You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 18:55:23