我正在使用GraphQL,并且无法找到将变量从查询传递到结果的最佳方法。
我有一个这样的架构:
type Fragment {
# The id of the fragment
id: String!
# The key of the fragment
key: String!
# The type of component
component_type: String!
# The params used to build the fragment
params: JSON
# Component data
data: JSON
children: [JSON]
items: [JSON]
}
该片段是指“cms”片段。我想在解析之后将一些查询数据传递到另一个后端。
我的查询如下:
query getFragmentsWithItems($keys: [String!]!
$platform: PlatformType
$version: String
$userInfo: UserInput
$userId: Int
) {
fragmentsWithItems(keys: $keys, platform: $platform, version: $version, userInfo: $userInfo, userId: $userId) {
key
data
children
params
items
}
}
问题在于:我在Fragment的data
字段中有一些查询数据。在Fragment
解决之前,该数据无法使用。我想获取该数据并将其发送到不同的后端。我想用GraphQL来做这件事,我希望做的事情如下:
Fragment: () => {
async query(obj, args, context, info, {modles}) => {
const items = await models.getItems(obj.query_string);
}
}
但我需要传递给原始查询的user_info
和user_id
。显然,只能从info
参数中访问,而这个参数不应该被使用。
我采取的另一条路径是拥有一个手动解析器,它可以做到这样的事情:
const resolveFI = ({ keys, platform, version, userInfo, userId, models }) => {
if (!keys || !keys.length) {
return Promise.resolve(null);
}
return models.release.get({ platform, version }).then(release =>
Promise.all(
keys.map(key =>
models.fragments.get({
key,
platform,
version,
release: release.id
})
)
).then(data => {
const promises = [];
data.rows.forEach(r => {
if (r.data.query_data) {
const d = {
// Can just ignore
filters: r.data.query_data.filters || {},
user_info: userInfo,
user_id: userId
};
promises.push(
new Promise(resolve => {
resolve(
models.itemSearch.get(d).then(i => ({ items: i.items, ...r }))
);
})
);
}
...etc other backends
这是有效的,但手动承诺链似乎无法使用GraphQL。
我尝试的最后一件事是让items
成为非标量类型,例如:
type Fragment {
items: ItemSearchResult(user_info: UserInput) etc
但是因为我无法将实际结果从Fragment传递给无效的ItemSearchResult。
我意识到这是非常啰嗦的,所以我愿意接受编辑或澄清 我想看看我是否错过了一个更好的方法,或者我是否应该将其打包并让客户端应用程序在获取Fragment数据后再执行项目查询。
答案 0 :(得分:1)
并不是说你不应该使用info
- 这只是一个巨大的痛苦使用;)严肃地说,它是' s意味着用于优化和更高级的用例,因此如果没有更好的解决方案,您就不应该使用它。有些库(like this one)可以用来更容易地解析对象。
那就是说,有几种方法,我想你可以解决这个问题:
1。)在查询解析程序中
getFragmentsWithItems: async (obj, args, ctx, info) => {
const fragments = await howeverYouDoThat()
const backendCalls = fragments.map(fragment => {
// extract whatever data you need from the fragment
return asyncCallToBackEnd()
})
await backendCalls
return fragments
}
不幸的是,如果你有很多不同的查询返回片段,你最终会得到冗余。
2。)在Fragment类型的现有字段(或另外一个字段)的解析器内部。
如果你走这条路线,并且你需要传递给查询字段的args,你可以使用信息提取它们。或者,您也可以在查询解析程序中改变上下文对象并将这些参数附加到它。然后,所有解析器"下面"查询解析器(如Fragment字段的解析器)可以通过上下文访问这些参数。
3.。)Apollo Server允许您在配置其中间件时定义formatResponse
功能。这本质上提供了一个钩子,可以在响应返回给客户端之前对响应执行任何操作。您可以解析该函数内部的响应,并从那里调用另一个后端。