GraphQL 查询中的多项查找

Multiple item lookup in GraphQL Query

我想知道基于 ID 查找多个项目的最常用方法是什么。根据我天真的理解,我看到了 3 个选项:

选项 1

接受 ID 数组和return 所有结果

products(ids: [ID!]!): [Product!]!

这似乎是最直接、最直观的方法,但不允许客户端对结果进行索引,并且偏离了其他查询通常遵循的分页模式。

选项 2

强制客户使用别名

product(id: ID!): Product!

这在服务器端最容易实现,并且还允许客户端根据 ID 直接对结果进行索引(假设他们使用 ID 作为别名),但也会强制客户端构建更复杂的查询。

选项 3

接受 ID 数组和 return 分页结果(通过连接模式)

products(ids: [ID!]!, after: String, first: Int! = 10): ProductConnection!

这与 return 分页结果的其他查询保持一致,但也有与 #1 相同的问题,不允许客户端通过 ID 直接索引到结果(假设 ID 用作别名如选项 2)。对于不熟悉的用户来说,连接模式也不是很直观。

根据您的经验有什么建议吗?谢谢!

这个答案不一定会介绍更多的做事方式,但我会详细说明我为我的模式找到的一些最佳实践,以及它们与社区项目的关系。

选项 2 不适用于静态查询

正如我已经在评论中讨论的那样,请考虑您的应用真正需要什么。如果你想通过 ID 查找动态数量的字段,当你想使用 static queries 时,选项 2 不会有帮助。您必须连接字符串才能大致像这样创建动态查询:

const query = `{ ${ids.map(id => `product${id}: product { ...Frag }\n`).join('')} }`;

这是一个坏主意,链接的文章讨论了原因以及您的 GraphQL 端点可能不是为此而设计的。我们也可以为每个产品一个一个地发送多个查询,但是这样我们就失去了 GraphQL 相对于 REST 的一个关键优势。

但是: 我们通常保留用于查询单个实体的字段,因为查看单个项目通常是我们应用程序的一个用例,我们可以非常快速地响应该查询。请参阅我对查询的回答的最后一部分。

其他两个选项基本相同

选项 1选项 3 应该在您的项目中始终如一地选择。该连接在查询 ID 时可能并没有真正的帮助,但它可以防止 return 访问许多项目并与 Relay 无缝集成。

您还需要考虑如何将前端的 ID 与值再次连接起来。您 return 项目的顺序是否与查询的顺序相同(例如从 Dataloader 中得知),或者您是否查询实体的 ID 并且顺序无关紧要。

因此,如果您所有查询 return 多个项目 return 连接,那么我也会在这里进行。危险在于查询会变得复杂,这导致我进入最后一个主题。

通用过滤器被认为是有害的

一般来说,建议仅将前端真正需要的查询公开为 this Twitter thread elaborates and Lee Byron (one of the creators) adds that you should also only expose queries that you can fulfill efficiently. In contrast Apollo recommends to not couple clients and server implementations 而不是抽象模式。我想你必须找到一个平衡点。

我认为公开一个非常具体的过滤器对象几乎与每次创建一个新字段一样好,但它可能无法很好地扩展。您将很快需要构建复杂的查询,而查询构建器库可能会有所帮助。另一方面,如果您已经准备就绪 - 就像在您的示例产品中可能已经是高度可过滤的 - 添加它会非常容易。

有些项目在野外提供了广泛的过滤器,如 Hasura, Prisma and Gatsby。因此,如果您想构建更多通用过滤器,您可以从这些项目中汲取灵感。