您尝试实现的第一件事(重用参数)可以使用GraphQL variables 完成。然而,据我所知,第二件事(重用输出值作为输入)无法实现。
然而,两者听起来都像您的类型关系没有正确定义。让我们更详细地了解这些要点。
使用变量重用参数
TL;DR 变量是重用参数的关键概念,但在 OP 描述的情况下可能并不理想。请参阅下面此答案的第二部分。我将其留在这里以提供完整的详细信息。
GraphQL variables 非常适合定义一次参数并多次使用。
使用swapi-graphql 的最小示例如下所示:
query SomePeopleAndCompatriots($numberOfResults: Int) {
allPeople(first: $numberOfResults) {
name
homeworld {
name
residents(first: $numberOfResults) {
name
}
}
}
}
同时声明以下变量:
{ "numberOfResults": 3 }
实际上,此 API 实现了notions of node and edges,因此实际查询有点复杂,但请随意play with it。
This reference 将为您提供有关如何使用 GraphQL.js 使用参数的更多详细信息,但由于您没有提供与您的架构声明相对应的代码,因此您需要调整详细信息。
在您的情况下,在我看来您已经将coordinates 定义为输入类型。假设您拨打了CoordinatesInput,您的查询现在看起来像(故意省略venueId,请参阅下面的此答案的其余部分):
query MoviesAndVenuesAndEvents($coordinates: CoordinatesInput) {
movies(coordinates: $coordinates) {
id
venues (coordinates: $coordinates) {
id
events (coordinates: $coordinates) {
id
}
}
}
}
传递对应的变量:
{ "coordinates": { "latitude": 51.509865, "longitude": -0.118092 } }
这会如您所愿,但这可能不是最好的路线,我们将在下面看到。
改善你的类型关系
使用我拥有的信息,您的查询,看起来movies、venues 和events 后面的类型彼此不知道。这意味着您的架构无法利用 GraphQL 的所有功能。将您的架构想象成一棵树,其中events 是venue 的子代,venues 是movies 的子代。
对于venueId,您甚至不需要它。
让我们对您的模式声明做一些假设。你的VenueType 看起来像这样:
const VenueType = new GraphQLObjectType({
name: 'Venue'
id: /* ... */,
// ...
events: {
type: new GraphQLList(EventType),
description: 'All events happening at this venue',
resolve: venue => venue.getEvents()
)
});
当您对来自venues 的所有结果查询events 时,您实际上请求解析器在给定的venue 上调用getEvents(),您可以对其进行操作。我不知道您的实现,但它可以简单地执行venue.events 或Event.findAllByVenue(venue.id) 等。在这里您可以确保只检索该特定场地的事件,而不是您存储中的所有事件。
This example 将为您提供有关如何执行此操作的更多详细信息。
同样,MovieType 应该有venues 解析为movie => movie.getVenues(),这就是为什么我的答案的第一部分不适合您的情况。最后,您的查询应如下所示:
query MoviesAndVenuesAndEvents($coordinates: CoordinatesInput) {
movies(coordinates: $coordinates) {
id
venues {
id
events {
id
}
}
}
}
它本质上是说:“给我这些坐标的所有电影,并为每部电影给我所有场地和这些场地的所有事件”。
如果您要获取的是在给定区域播放的所有电影(目前仅关注电影和场地,但您可以将其推断为事件),那么您的查询可能应该是:
venues(coordinates: $coordinates) {
id
movies
}
但最后一个示例可能会为您提供必须在客户端上展平的重复项。要首先关注电影,您将使用前面的示例,确保您的 movies 解析器仅检索传递坐标的电影。再次对您的后端进行完整的假设,它可能看起来像这样:
resolve: coordinates => allMovies.filter(movie =>
movie.venues.some(venue => venue.coordinates === coordinates)
)