How to pass variable to GraphQL for fields to sele

2019-08-21 19:40发布

问题:

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?

回答1:

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.



回答2:

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|).