GraphQL 查询中的数据规范化

Data normalization in GraphQL query

我正在使用 GraphQL 查询具有两种数据类型的数据库:UserGroup

组有一个字段 users,它是该组中 User 个对象的数组。我在根目录中有一个名为 groups 的字段,其中 return 是我所有组的数组。

一个典型的查询可能看起来像这样:

{
    groups {
        id,
        name,
        users {
            id,
            name,
            address,
            email,
            phone,
            attitude,
            job,
            favoriteQuote,
            favoriteColor,
            birthday
        }
    }
}

问题是这些用户中有很多可以属于多个组,并且鉴于 User 有很多字段,这会使响应非常大。

有没有办法为对象的第一个实例获取一组字段,并为响应中的每个其他实例获取一组不同的字段?

我只需要 namejobemail 等响应中的每个用户一次,之后只需要 id(我可以自己进行标准化之后)。

或者

有什么方法可以只获取组中所有用户的 id 字段和 return 已引用的所有唯一 User 对象的单独数组在查询中(不是 all User 个对象)?

一般 - 通常

...规范化...当然...f.e。使用 apollo 并且它是标准化缓存。

从 API 编辑的所有记录 return 必须具有相同的形状。

您可以仅使用查询 ID 和名称 (full/paginated) 获取数据并呈现一些 <MembersList/> 组件。

稍后您可以在某些 <UserProfile/> 组件中使用自己的查询(在内部挂钩 useQuery)呈现详细信息,以从 cache/api(可控)获取额外数据。

您的具体要求 - 可能

第一个选项:

通常响应是一种常见的形状(根据要求),但您可以根据解析器级别决定要 return 的内容。这需要更改查询结构以允许 (API, backend) 使某些属性无效化。 F.e.

group {
    id
    name
    users {
        id
        name
        profile {
          photo
          email
          address

使用 profile 自定义 json 类型...您可以将用户解析器构建为 return 仅针对第一条记录的完整数据和针对所有后续用户的 null

第二个选项:

您可以在一个请求中使用 2 个略有不同的查询。使用别名(参见文档),简而言之:

groupWithFullMember: group ( groupId:xxx, limitUsers:1 ) {
    id
    name
    users {
        id
        name
        address
        email
        ...
    }
}

groupMembers: group ( groupId:xxx ) {
    id
    name // not required
    users {
        id
        name
    }
}

组解析器可以 return 它是子 users ... 或 users 解析器可以访问 limitUsers 参数以限制 response/modify 数据库查询。

Is there any way to get one set of fields for the first instance of an object, and a different set for every other instance in the response?

没有。除非单个项目的类型不同,否则将为列表中的每个项目 returned 设置相同的字段集,因为可以在运行时为每种类型 returned 指定单独的选择集。

Is there any way to only get id fields for all users in groups and return a separate array of all unique User objects that have been referenced in the query (which is not all User objects)?

您可以设计您的模式来适应这一点。像

{
  groups {
    nodes {
      id
      name
      users {
        id
      }
    }
    uniqueUsers {
      id
      # other fields
    }
  }
}

您的 groups 解析器需要处理所有规范化和 return 适当形状的数据。然而,一个更简单的解决方案可能是反转你的关系:

{
  users {
    id
    name
    address
    email
    phone
    attitude
    job
    favoriteQuote
    favoriteColor
    birthday
    groups {
      id
      name
    }
  }
}