我想知道基于ID查找多个项目的最常用方法是什么。从我的天真理解,我看到3个选项:
接受ID数组并返回所有结果
products(ids: [ID!]!): [Product!]!
这似乎是最直接,最直观的方法,但不允许客户索引结果和其他查询通常遵循的分页模式所产生的偏差。
强制客户端使用别名
product(id: ID!): Product!
这是最容易在服务器端实现的方法,并且还允许客户端根据ID直接将结果编入索引(假设他们使用ID作为别名),但也可以强制客户端构造更复杂的查询。
接受ID数组并返回分页结果(通过连接模式)
products(ids: [ID!]!, after: String, first: Int! = 10): ProductConnection!
这与其他返回分页结果的查询保持一致,但是也存在与#1相同的问题,即不允许客户端通过ID直接索引到结果中(假设ID与选项2一样被用作别名)。对于不熟悉它的用户来说,连接模式也不是立即直观的。
根据您的经验有什么建议吗?谢谢!
答案 0 :(得分:1)
这个答案并没有必然地引入更多的做事方式,但是我将详细阐述一些关于我的模式以及它们与社区项目之间的关系的最佳实践。
正如我在评论中已经讨论过的那样,请思考您的应用程序真正需要什么。如果要使用ID 选项2 查找动态字段数,则在使用static queries时将无济于事。您将必须添加字符串以创建大致如下的动态查询:
const query = `{ ${ids.map(id => `product${id}: product { ...Frag }\n`).join('')} }`;
这是一个坏主意,链接的文章讨论了原因以及您的GraphQL终结点可能不是为此而设计的。我们也可以针对每个产品一个接一个地发送多个查询,但随后我们就失去了GraphQL与REST相比的一项主要优势。
但是:我们通常保留用于查询单个实体的字段,因为查看单个项目通常是我们应用程序的用例,我们可以非常快速地响应该查询。请参阅我对查询的回答的最后一部分。
选项1 和选项3 。在查询ID时,该连接可能实际上并没有帮助,但可以防止返回许多项目并与Relay无缝集成。
您还需要考虑如何将前端的ID重新与值连接。您是否按照查询的顺序返回项目(例如从Dataloader中得知),还是查询实体的ID,而顺序无关紧要。
因此,如果您所有返回多个项目的查询都返回了连接,那么我也将在此处进行连接。危险在于查询将变得复杂,这将导致我进入最后一个主题。
通常,建议仅将前端确实需要的查询公开为this Twitter thread elaborates,而Lee Byron(创建者之一)添加that you should also only expose queries that you can fulfill efficiently。相反,Apollo建议使用not couple clients and server implementations,而不是抽象模式。我认为您必须找到一个平衡点。
我认为每次公开一个非常具体的过滤器对象几乎和每次创建一个新字段一样好,但是可能无法很好地扩展。您将很快需要构建复杂的查询,而查询构建器库可能会有所帮助。另一方面,如果您已经准备好了它(例如您的示例产品可能已经可以大量过滤),则添加起来非常容易。
一些野外项目提供了广泛的过滤器,例如Hasura,Prisma和Gatsby。因此,如果您想构建更多的通用过滤器,则可以从这些项目中汲取灵感。