You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从数组动态构建GraphQL片段并生成查询?

动态构建GraphQL查询(基于片段数组)

我了解到构建动态GraphQL查询的推荐方式是使用片段,静态场景下的示例如下:

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
      }
    }
  }
`

随后将这些片段拼入主查询:

export const mainQuery = gql`
    query fetchData {
      ...series1 
      ...series2
    }
    ${series1Q}
    ${series2Q}
`  

但我的场景中用户可添加任意数量的项,最终会得到一个片段数组:

const series = 
[
    gql`
        fragment series1 on timeseriesDataQuery {
            series1: timeseriesData(sourceId: "source1") {
                data {
                    time
                    value
                }
            }
        }
    `,
    gql`
        fragment series2 on timeseriesDataQuery {
            series2: timeseriesData(sourceId: "source2") {
                data {
                    time
                    value
                }
            }
        }
    `
]

我尝试过多种拼接方式均出现格式错误,例如:

export const mainQuery = gql`
    ${...series}
    query fetchData {
      ...series1 
      ...series2
    }
`  

或者:

export const mainQuery = gql`
    {...series}
    query fetchData {
      ...series1 
      ...series2
    }
`  

请问有没有人实现过从数组创建动态GraphQL查询?


解决方案

要处理动态片段数组,需分两步完成:生成查询内的片段引用列表,以及拼接所有片段定义。

步骤1:生成动态片段引用

从片段数组中提取每个片段的名称,生成对应的...片段名语句并拼接成字符串,插入到查询的字段位置。

步骤2:拼接片段定义

将数组中的所有片段用join('')拼接后,插入到主查询的末尾。

代码示例(片段名称按顺序生成)

// 从片段数组提取名称,假设名称是series1、series2格式
const fragmentNames = series.map((_, index) => `series${index + 1}`);
// 生成片段引用字符串
const fragmentRefs = fragmentNames.map(name => `...${name}`).join('\n      ');

export const mainQuery = gql`
    query fetchData {
      ${fragmentRefs}
    }
    ${series.join('')}
`  

代码示例(片段名称不固定时)

如果片段名称不是按顺序生成的,可以通过正则从片段内容中提取名称:

// 从片段字符串中提取名称的工具函数
const getFragmentName = (fragment) => {
  const match = fragment.loc.source.body.match(/fragment (\w+) on/);
  return match ? match[1] : '';
};

const fragmentNames = series.map(getFragmentName).filter(Boolean);
const fragmentRefs = fragmentNames.map(name => `...${name}`).join('\n      ');

export const mainQuery = gql`
    query fetchData {
      ${fragmentRefs}
    }
    ${series.join('')}
`  

核心逻辑是利用模板字符串结合数组join方法,完成动态片段引用和定义的拼接,避免语法错误。

内容的提问来源于stack exchange,提问作者LuxuryWaffles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 09:20:33