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

Gatsby中GraphQL查询如何在where条件使用动态字段变量?

问题:Gatsby中GraphQL查询能否动态指定where条件的字段名?

我正在使用Gatsby和GraphQL构建网站,通过Gatsby的createPage API创建页面,数据源来自Hygraph。

我可以通过gatsby-node.js文件的createPage的context参数向模板传递动态值,代码如下:

createPage({
  path: `/path-to-my-page`,
  component: require.resolve(`./src/my-template.js`),
  context: {
    product_attribute: "metal",
    product_attributeValue: "silver"
  },
})

在模板中编写页面查询时,传递product_attributeValue动态值的代码可以正常运行:

export const pageQuery = graphql`
  query ProductListingByAttributeQuery(
    $product_attribute: String
    $product_attributeValue: String
  ) {
    gcms {
      products(
        orderBy: updatedAt_DESC
        where: {
          metal: $product_attributeValue
        }
      ) {
        slug
        title
        image
        content
      }
    }
  }
`

但我希望用product_attribute变量替代where条件中的固定字符串'metal',写法如下:

where: {
    $product_attribute: $product_attributeValue
}

此时出现语法错误:“Syntax Error: Expected Name, found $”。请问是否可以实现这种需求?即使用product_attribute变量作为where条件的字段名。


解决方案

GraphQL本身不支持直接用变量作为字段名——它是静态类型查询语言,字段名必须在编写查询时确定,所以你那种直接用$product_attribute当字段名的写法会报错,这是正常的。下面给你两个可行的解决办法:

方案1:在gatsby-node.js中提前查询数据,再传递给模板

既然createPage的context能传值,不如在生成页面之前就把对应属性的产品数据查出来,直接传给模板,这样模板里就不用写动态查询了:

// gatsby-node.js
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;

  // 示例:定义需要生成页面的属性组合
  const attributePages = [
    { attribute: "metal", value: "silver" },
    { attribute: "material", value: "wood" },
    // 更多属性组合...
  ];

  for (const page of attributePages) {
    // 构建动态where条件
    const whereCondition = { [page.attribute]: page.value };
    
    // 执行GraphQL查询获取对应产品数据
    const result = await graphql(`
      query GetProductsByAttribute($where: ProductWhereInput) {
        gcms {
          products(orderBy: updatedAt_DESC, where: $where) {
            slug
            title
            image
            content
          }
        }
      }
    `, { where: whereCondition });

    // 创建页面,把查询到的产品数据传给模板
    createPage({
      path: `/products/${page.attribute}/${page.value}`,
      component: require.resolve(`./src/my-template.js`),
      context: {
        products: result.data.gcms.products,
        attribute: page.attribute,
        value: page.value,
      },
    });
  }
};

然后模板里直接用pageContext中的数据渲染,不需要写pageQuery:

// src/my-template.js
export default function ProductListingTemplate({ pageContext }) {
  const { products, attribute, value } = pageContext;
  
  return (
    <div>
      <h1>{attribute}: {value}</h1>
      {products.map(product => (
        <div key={product.slug}>
          <h2>{product.title}</h2>
          {/* 渲染其他产品信息 */}
        </div>
      ))}
    </div>
  );
}

方案2:用GraphQL的条件运算符覆盖所有可能的属性

如果一定要在模板的pageQuery里处理,可以把所有可能的属性字段都写进查询,用变量控制哪个字段生效。比如假设你的产品只有metal、material、color这几个属性:

export const pageQuery = graphql`
  query ProductListingByAttributeQuery(
    $product_attribute: String
    $product_attributeValue: String
  ) {
    gcms {
      products(
        orderBy: updatedAt_DESC
        where: {
          _or: [
            { metal: $product_attributeValue },
            { material: $product_attributeValue },
            { color: $product_attributeValue }
          ],
          _and: [
            # 只保留和当前属性匹配的条目
            { metal: { _exists: $product_attribute === "metal" } },
            { material: { _exists: $product_attribute === "material" } },
            { color: { _exists: $product_attribute === "color" } }
          ]
        }
      ) {
        slug
        title
        image
        content
      }
    }
  }
`

这种方法的缺点是如果属性很多,查询会变得冗长,但胜在不用修改gatsby-node.js的核心逻辑,直接在模板里处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 05:15:41