Mat*_*son 11 apollo graphql apollo-client graphql-tag
我有一个GraphQL服务器,它能够为指定的源(例如,传感器数据)提供时间序列数据.获取传感器数据的示例查询可能是:
query fetchData {
timeseriesData(sourceId: "source1") {
data {
time
value
}
}
}
Run Code Online (Sandbox Code Playgroud)
在我的前端,我希望允许用户选择一个或多个源,并显示一个图表,每个图表都有一行.看起来这可以通过使用这样的查询:
query fetchData {
series1: timeseriesData(sourceId: "source1") {
data {
time
value
}
}
series2: timeseriesData(sourceId: "source2") {
data {
time
value
}
}
}
Run Code Online (Sandbox Code Playgroud)
大多数GraphQL教程似乎都专注于静态查询(例如,唯一改变的是变量,而不是请求的实际形状) - 但在我的情况下,我需要查询本身是动态的(每个都有一个timeseriesData请求)我选择的ids).
我有以下约束:
我正在使用的堆栈是:
理想情况下,我想要做的是有一些方法将两个查询合并为一个,这样我就可以按照第一个例子定义它们,然后将它们连接在一个抽象层中,这样我得到一个像第二个例子一样的查询通过电汇发送.
但是我不确定如何实现这一点,因为graphql-tag正在将查询解析为AST,而我正在努力理解以这种方式操作查询是否可行.
有哪些技术可以生成像这样的动态查询,其中查询的形状不是预先知道的?
snn*_*snn 14
您可以使用片段来定义公共字段,并使用该片段上的变量绑定@include(if: Boolean)和@skip(if: Boolean)指令来获取执行时已知的动态字段。
根据规范,最好避免手动字符串插值来构建动态查询。
指令1可以根据作为查询变量传递的布尔表达式来包含或跳过字段。指令可以附加到字段或片段包含,并且可以以服务器期望的任何方式影响查询的执行。
query Hero($episode: Episode, $withFriends: Boolean!) {
hero(episode: $episode) {
name
friends @include(if: $withFriends) {
name
}
}
}
Run Code Online (Sandbox Code Playgroud)
在变量中:
{
"episode": "JEDI",
"withFriends": false
}
Run Code Online (Sandbox Code Playgroud)
当然,您可以像在第二个示例中一样发送命名查询。客户端将自动批处理请求。
我认为当用户动态选择传感器时,您别无选择,只能使用 String 功能,甚至您在开发时(不是运行时)也不知道传感器。
const mainQuery = gql
`query fetchData($sourceId: String!) {
timeseriesData(sourceId: $sourceId) {
data {
time
value
}
}
}`;
const mainQueryStr = mainQuery.loc.source.body;
Run Code Online (Sandbox Code Playgroud)
这mainQueryStr是查询的字符串值(以处理问题的动态性)然后在传感器上循环并替换$sourceId为每个传感器的 id
// You have to remove the query wrapper first
// Then replace sensor id
const sensorsQueries = sensors.map(sid => mainQueryStr
.split(`\n`)
.slice(1, 7)
.replace(`$sourceId`, sid)
)
Run Code Online (Sandbox Code Playgroud)
然后你应该加入 sensorQueries 并进行新的 GraphQL 查询
const finalQuery = gql`
query fetchData {
${sensorsQueries.join(`\n`)}`
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您可以使用工具优势,例如自动完成、语法突出显示和 ... 用于mainQuery查询,而不是finalQuery(因为您动态创建了这个)
我认为您可以为此使用片段!但是"queries"在这种情况下你仍然必须写 2 fragments。
首先让我们fragment为每个创建一个timeSeries,请检查您的 timeSeries 查询类型,我将其称为timeseriesDataQuery
const series1Q = gql`
fragment series1 on timeseriesDataQuery {
series1: timeseriesData(sourceId: "source1") {
data {
time
value
}
}
}
}
const series2Q = gql`
fragment series2 on timeseriesDataQuery {
series2: timeseriesData(sourceId: "source2") {
data {
time
value
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在查询中将它们拼接起来:
export const mainQuery = gql`
query fetchData {
...series1
...series2
}
${series1Q}
${series2Q}
`
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5249 次 |
| 最近记录: |