Khaino
Khaino

Reputation: 4169

How to pass variable to GraphQL for fields to select

My sample query is as below:

%{
      "query" => """
        query getPerson(
            $name: String!
          ){
            getPerson(name: $name) {
              id
              col1
              col2
              col3
              col3
            }
          }
      """,
      "variables" => %{
        "name" => "person_name",
      }
    }

I want to select the fields dynamically. For example, for one query I just need id, col1, col2 but for another query id, col1, col3 and so on. How do I use variable for fields?

Below is what I try which is not correct.

%{
          "query" => """
            query getPerson(
                $name: String!
              ){
                getPerson(name: $name) {
                  $fields
                }
              }
          """,
          "variables" => %{
            "name" => "person_name",
            "fields" => "id col1 col3",
          }
        }

I am new to graphql. Can anyone help me write it correctly?

Upvotes: 1

Views: 3856

Answers (3)

tomiplaz
tomiplaz

Reputation: 486

You could use the @include directive to include the col2 field based on a flag variable:

query getPerson($name: String!, $withCol2: Boolean = false) {
  getPerson(name: $name) {
    id
    col1
    col2 @include(if: $withCol2)
    col3
  }
}

See https://graphql.org/learn/queries/#directives

Upvotes: 3

David Maze
David Maze

Reputation: 159830

You can't natively do this in GraphQL. Variables only provide specific (input) values and don't define the structure of the query. (The same thing is true in most SQL implementations.)

You can read through the grammar in the GraphQL specification to see what's allowed in, for instance, a selection set; it's just not allowed to use variables in the way you suggest.

One alternative that minimizes the amount of string manipulation you need to do is to use named fragments to package up a list of requested fields. It's allowed to send fragments you don't actually use. You could restructure your query as

fragment PersonParts on Person { id col1 col2 col3 }
query GetPerson($name: String!) {
  getPerson(name: $name) { ...PersonParts }
}

and if you have multiple named fragments just swap that out, instead of trying to dynamically construct the field list.

Upvotes: 4

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

The query there is a plain old good string, hence I would go with string interpolation in Elixir instead of trying to use GraphQL variables.

defmodule M do
  def query!(fields) when is_list(fields) do
    fields = Enum.join(fields, "\n        ")

    query =
      ~s"""
        query getPerson(
            $name: String!
          ){
            getPerson(name: $name) {
              #{fields}
            }
          }
      """
    %{
      "query" => query,
      "variables" => %{
        "name" => "person_name",
      }
    }
  end
end

And use it as M.query!(~w|id col1 col2|).

Upvotes: 0

Related Questions