GraphQL: запрос и изменение в одном сетевом вызове - PullRequest
1 голос
/ 05 июня 2019

Я собираюсь привести конкретный пример с API GitHub GraphQL (что является конкретной проблемой, которую я хочу решить), но этот вопрос кажется обобщенным для GraphQL в целом.

Предположим, я хочу добавить метку 'high priority' к проблеме # 1234 в репозитории pytorch / pytorch. Согласно документации API, я должен использовать мутацию https://developer.github.com/v4/mutation/addlabelstolabelable/ Входные требования:

labelIds ([ID!]!)
The ids of the labels to add.

labelableId (ID!)
The id of the labelable object to add labels to.

ОК, как мне получить идентификаторы? В моем коде я знаю, что хочу метку «высокий приоритет», но чтобы на самом деле сообщить об этом этой мутации, я должен сначала преобразовать «высокий приоритет» в идентификатор, но сначала выполнить другой вызов GraphQL. То же самое относится к тому, что я хочу пометить: у меня есть уникальный идентификатор в форме pytorch / pytorch # 1234, но у меня нет идентификатора, я должен его посмотреть.)

Итак, в конце дня мне нужно сделать три API-вызова, чтобы просто что-то пометить, когда я мог бы сделать это в REST вместо одного вызова. В общем, я вижу множество API мутаций GraphQL, которые общаются только в идентификаторах (даже когда для системы доступен какой-то другой канонический идентификатор), и в итоге мне приходится совершать дополнительные обходы. Я делаю это неправильно? Или это действительно так, как был разработан GraphQL?

1 Ответ

1 голос
/ 05 июня 2019

Согласно spec , документ GraphQL может содержать любое количество операций , где операция является одной из query, mutation или subscription.

  • запрос - выборка только для чтения.
  • мутация - запись с последующей выборкой.
  • подписка - долгоживущий запрос, который извлекает данные в ответ на исходные события.

Только одна операция может быть выполнена для конкретного запроса (если предоставляется более одного, необходимо указать operationName, чтобы указать, какой из них должен быть выполнен).

Однако в рамках этой операции может быть запрошено любое количество полей. Таким образом, если вам нужно два или более полей запроса корневого уровня (в разговорной речи называемые «запросы»), они могут быть объединены в одну операцию:

query ArbitraryOperationName {
  getSomething
  getSomethingElse
}

То же самое для мутаций - вы можете выполнить две или более мутации (последовательно):

mutation ArbitraryOperationName {
  doSomething
  doSomethingElse
  doAThirdAction
}

Таким образом, единственные сценарии, в которых вам нужно разделить ваш запрос на несколько запросов:

  • Вам необходимо выполнить и query, и mutation - это отдельные операции, поэтому их нужно отправлять отдельно.
  • Вам необходимо предоставить часть результата одного запроса в качестве входного для другого.

Вы должны иметь возможность получить и идентификатор метки, и идентификатор проблемы в одном запросе:

query {
  repository(owner: "graphql", name: "graphql-js") {
    label(name: "help wanted") {
      id
    }
    issue(number: 100) {
      id
    }
  }
}

Однако ваша мутация должна быть отдельным запросом, потому что 1) это другая операция и 2) она требует в качестве входных данных, возвращаемых вышеуказанным запросом.

Тем не менее, тот факт, что addlabelstolabelable требует, чтобы вы передавали идентификаторы вместо имен для меток и идентификаторы вместо номеров для выпусков / PR, это выбор дизайна со стороны Github. Хотя довольно часто можно видеть объекты, на которые явно ссылается какое-то поле id в аргументах мутации, в спецификации нет ничего, что запрещало бы мутации принимать другие идентификаторы в качестве входных данных.

...