Мой пример запроса выглядит следующим образом:
%{
"query" => """
query getPerson(
$name: String!
){
getPerson(name: $name) {
id
col1
col2
col3
col3
}
}
""",
"variables" => %{
"name" => "person_name",
}
}
Я хочу выбирать поля динамически. Например, для одного запроса мне нужен только id, col1, col2, а для другого - id, col1, col3 и так далее. Как использовать переменную для полей?
Ниже я попробую, но это неверно.
%{
"query" => """
query getPerson(
$name: String!
){
getPerson(name: $name) {
$fields
}
}
""",
"variables" => %{
"name" => "person_name",
"fields" => "id col1 col3",
}
}
Я новичок в graphql. Кто-нибудь может помочь мне написать это правильно?





Запрос представляет собой простую старую хорошую строку, поэтому я бы пошел с интерполяцией строк в Elixir вместо того, чтобы пытаться использовать переменные GraphQL.
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
И используйте его как M.query!(~w|id col1 col2|).
Хотя я не мог представить себе причин для отказа от интерполяции строк, другим вариантом было бы использовать Absinthe.Schema.Notation.resolve/1, предоставляемый Абсент.
Вы не можете сделать это изначально в GraphQL. Переменные предоставляют только определенные (входные) значения и не определяют структуру запроса. (То же самое верно в большинстве реализаций SQL.)
Вы можете прочитать грамматику в спецификации GraphQL, чтобы увидеть, что разрешено, например, в набор выбора; просто не разрешено использовать переменные так, как вы предлагаете.
Одна альтернатива, которая сводит к минимуму количество необходимых вам манипуляций со строками, - это использовать именованные фрагменты для упаковки списка запрошенных полей. Разрешено отправлять фрагменты, которые вы фактически не используете. Вы можете реструктурировать свой запрос как
fragment PersonParts on Person { id col1 col2 col3 }
query GetPerson($name: String!) {
getPerson(name: $name) { ...PersonParts }
}
и если у вас есть несколько именованных фрагментов, просто замените их, вместо того, чтобы пытаться динамически построить список полей.
Вы можете использовать директиву @include для включения поля col2 на основе переменной флага:
query getPerson($name: String!, $withCol2: Boolean = false) {
getPerson(name: $name) {
id
col1
col2 @include(if: $withCol2)
col3
}
}
Мой текущий код похож на код, который вы дали выше. Я забыл упомянуть, что не хочу использовать строковую интерполяцию в запросе, если это возможно по какой-либо причине. Итак, я пытаюсь найти способ удалить
#{fields}и использовать переменную.