Graphql 将多个查询合并(组合)为一个?

Hen*_*Jan 11 javascript graphql

我正在尝试使用 JavaScript 将多个 Graphql 查询合并为一个查询。
我正在寻找这样的东西:

let query3 = mergeQueries(query1, query2);
Run Code Online (Sandbox Code Playgroud)

我们事先不知道将合并哪些查询。

假设我有这样的查询:

输入查询1:

{
  post(id: 1234) {
    title
    description
  }
}
Run Code Online (Sandbox Code Playgroud)

输入查询2:

{
  post(id: 1234) {
    tags
    author {
      name
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我希望结果 query3 为:
result query3:

{
  post(id: 1234) {
    title
    tags
    description
    author {
      name
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这与 lodash_.merge()为 JSON 对象所做的功能相同,但随后使用 Graphql 查询而不是 JSON 对象。

Her*_*rku 9

我的回答有点太渴望发表评论了,所以我决定在这里写一个直接的回答。首先,我认为这两条评论都非常有帮助。有一个解决方案让两个查询共享一个 HTTP 请求,这可能已经是您正在寻找的优化。此外,合并查询并非易事。要做到这一点到现场级别需要付出很多努力。不仅片段会使这变得困难,您还必须考虑变量。据我所知,没有公开的解决方案可以做到这一点,所以你必须自己做。此外,我还没有听说过这样做的公司。我认为没有解决方案的事实表明这样做可能不值得。

我只能猜测您的问题,但减少前端应用程序发送的查询量的另一种方法是使用片段。虽然您的片段不能有变量,但健康的组件结构仍然非常适合片段:

fragment PostHeader on Post {
  title
  description
}

fragment PostMeta on Post {
  tags
  author {
    name
  }
}

query {
  post(id: 1234) {
    ...PostHeader
    ...PostMeta
  }
}
Run Code Online (Sandbox Code Playgroud)


Kev*_* K. 7

感谢参数化片段,您可以考虑变量!假设post是根查询类型的字段,引用上面示例的组合查询将是:

fragment PostHeader on RootQueryType {
  post(id: $id) {
    tags
    author {
      name
    }
  }
}

fragment PostMeta on RootQueryType {
  post(id: $id) {
    tags
    author {
      name
    }
  }
}

# ID being the id type
query($id: ID! = 1234) {
  ...PostHeader
  ...PostMeta
}
Run Code Online (Sandbox Code Playgroud)

或者更确切地说,在现实场景中,您将动态传递 id (例如在您的发布请求中),请参阅: https: //graphql.org/learn/queries/#variables


小智 7

我为此编写了一个库:https ://github.com/domasx2/graphql-combine-query

import comineQuery from 'graphql-combine-query'

import gql from 'graphql-tag'

const fooQuery = gql`
  query FooQuery($foo: String!) {
    getFoo(foo: $foo)
  }
`

const barQuery = gql`
  query BarQuery($bar: String!) {
    getBar(bar: $bar)
  }
`

const { document, variables } = combineQuery('FooBarQuery')
  .add(fooQuery, { foo: 'some value' })
  .add(barQuery, { bar: 'another value' })

console.log(variables)
// { foo: 'some value', bar: 'another value' }

print(document)
/*
query FooBarQuery($foo: String!, $bar: String!) {
   getFoo(foo: $foo)
   getBar(bar: $bar)
}
*/

Run Code Online (Sandbox Code Playgroud)