web-dev-qa-db-ja.com

GraphQL動的クエリの構築

指定したソースの時系列データ(たとえば、センサーデータ)を提供できるGraphQLサーバーがあります。センサーのデータを取得するクエリの例は次のとおりです。

query fetchData {
    timeseriesData(sourceId: "source1") {
      data {
        time
        value
      }
    }
}

私のフロントエンドでは、ユーザーが1つ以上のソースを選択し、各ソースに線のあるチャートを表示できるようにします。次のようなクエリを使用すると、これが可能になるようです。

query fetchData {
    series1: timeseriesData(sourceId: "source1") {
      data {
        time
        value
      }
    }
    series2: timeseriesData(sourceId: "source2") {
      data {
        time
        value
      }
    }
}

ほとんどのGraphQLチュートリアルは静的クエリに焦点を当てているようです(たとえば、変化しているのは変数だけで、リクエストの実際の形状ではない場合)-しかし、私の場合はクエリ自体が必要です動的にする(選択したIDごとに1つのtimeseriesDataリクエスト)。

次の制約があります。

  1. サーバーのスキーマを変更することはオプションではありません(たとえば、リゾルバにIDの配列を渡すことはできません)
  2. 私のクエリは、テンプレート文字列を使用して指定されますgql` ... `
  3. クエリを文字列として手動で作成する必要はありません。それは災害のレシピのように見え、ツールの利点(たとえば、オートコンプリート、構文の強調表示、リント)をすべて失うことになるためです。

私が使用しているスタックは次のとおりです。

  • Apolloクライアント(特にapollo-angular)
  • Angular
  • TypeScript
  • graphql-tag(クエリの定義用)

理想的には、2つのクエリを1つにマージする方法があるので、最初の例のようにそれらを定義できますが、2番目の例のような単一のクエリを取得するために抽象化レイヤーでそれらを結合できます有線で送信されます。

しかし、graphql-tagはクエリをASTに解析しているため、この方法でクエリを操作することが実行可能かどうかを理解するのに苦労しているため、これを達成する方法はわかりません。

クエリのshapeが事前にわからない場合、このような動的クエリを生成するためのテクニックは何ですか?

9
Matt Wilson

フラグメントを使用して共通フィールドを定義し、そのフラグメントで変数バインド@include(if: Boolean)および@skip(if: Boolean)ディレクティブを使用して、実行時に既知の動的フィールドを取得できます。

2
SnnSnn

このために fragments を使用できると思います!ただし、まだ2 "queries"この場合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
      }
    }
  }
}

そして、クエリでそれらをつなぎます:

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