首页 > 解决方案 > GraphQL 查询中的多项查找

问题描述

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

选项1

接受 ID 数组并返回所有结果

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

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

选项 2

强制客户端使用别名

product(id: ID!): Product!

这在服务器端最容易实现,也允许客户端根据 ID 直接索引到结果中(假设他们使用 ID 作为别名),但也迫使客户端构造更复杂的查询。

选项 3

接受 ID 数组并返回分页结果(通过连接模式)

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

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

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

标签: graphqlgraphql-jsgraphql-java

解决方案


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

选项 2 不适用于静态查询

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

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

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

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

其他两个选项基本相同

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

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

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

被认为有害的通用过滤器

一般来说,建议只公开你的前端真正需要的查询,因为这个 Twitter 线程详细说明,Lee Byron(创建者之一)补充说,你也应该只公开你可以有效完成的查询。相比之下,Apollo 建议不要将客户端和服务器实现耦合,而是使用抽象模式。我认为你必须找到一个平衡点。

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

一些野外项目提供了广泛的过滤器,如HasuraPrismaGatsby。因此,如果您想构建更通用的过滤器,您可以从这些项目中获得灵感。


推荐阅读