Introduction to future-oriented Api--github graphql API usage

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.
This article, based on the GitHub developer documentation, organizes the use of the GitHub GRAPHQL API, and you can learn about the basic concepts of GRAPHQL, the use of GitHub GRAPHQL APIs, two practical use cases, and using Explorer to query the GitHub graphql API

On May 22 this year, GitHub announced that the GitHub GRAPHQL API, launched last year, was officially available (Production-ready) and recommended that integrators use the latest version of the GRAPHQL API V4 in the GitHub app.

I believe everyone is not unfamiliar with GRAPHQL, this Facebook launched the interface query language, determined to be concise and extensibility beyond rest, and has been applied in many complex business scenarios. GitHub describes why they favour GRAPHQL:

we chose GRAPHQL for API V4 because it provides significant flexibility for our integrators. Its most powerful advantage over rest API V3 is that you can precisely define the data you need and have no redundancy. With GRAPHQL, you only need a single request to get the data that can be obtained through multiple rest requests.

In the GitHub developer documentation There is a more complete GRAPHQL API v4 Introduction, this article organized and translated some of the content, and in accordance with the following chapters to organize, I hope to get started graphql or interested in the development of GitHub app students to reference:

    • Conceptual interpretation
    • How to use
    • Demonstration cases
    • Documentation Guidelines

Conceptual interpretation

The GitHub GRAPHQL API V4 is architecturally and conceptually different from the GitHub REST API v3, and you will encounter many new concepts in the GRAPHQL API V4 documentation.

Schema

The schema defines the type system for the GRAPHQL API. It completely describes all the data that the client can access (objects, member variables, relationships, any type). The client's request is verified and executed according to the schema. The client can obtain information about the schema through "introspection" (introspection). Schema is stored in the GRAPHQL API server.

Field

field is a unit of data that you can get from an object. As the official GRAPHQL document says, "The GRAPHQL query language is essentially selecting field from the object."

Regarding field, the official standard also says:

all GRAPHQL operations must indicate to the lowest field, and the return value is scalar to ensure the structure of the response result is clear

Scalar (scalar): basic data type

That is, if you try to return a Field,schema checksum that is not a scalar, an error will be thrown. You must add a nested internal field until all field returns a scalar.

Argument

argument is a set of key-value pairs appended to a specific field. Some field requests include argument. Mutation requires an object to be entered as a argument.

Implementation

GRAPHQL schema can use implement to define which interface the object inherits from.

Here is an example of an artificial schema that defines interface X and object Y:

interface X {  some_field: String!  other_field: String!}type Y implements X {  some_field: String!  other_field: String!  new_field: String!}

This means that object Y is also required to have the Field/argument/return type of interface x in addition to its own field. (! The field is required to represent)

Connection

Connection allows you to query the associated object in the same request. With connection, you only need a GRAPHQL request to complete multiple requests in the rest API.

To help understand, imagine a diagram like this: Many points are connected through a line. These points are node, and these are the edge lines. Connection defines the relationship between node.

Edge

Edge represents the connection between node. When you query a connection, you reach node through the edge. Each Edgesfield has a nodefield and a cursorfield. The cursor is used for paging.

Node

node is a generic type of object. You can query a node directly, or you can get the relevant node via connection. If you specify that node is not a return scalar, you must include the internal field in it until all field returns a scalar.

Basic use

Discover the GRAPHQL API

GRAPHQL is self-reflective, meaning that you can know its own schema details by querying a graphql.

    • Query __schema to list all the types defined in the schema and get the details of each:
query {  __schema {    types {      name      kind      description      fields {        name      }    }  }}
    • Query __type to get any type of detail:
query {  __type(name: "Repository") {    name    kind    description    fields {      name    }  }}
tip: Introspection queries may be the only get requests that you have in GRAPHQL. Whether it is query or mutation, if you want to pass the request body, the GRAPHQL request should be a post

GRAPHQL Authorization

To communicate with the GRAPHQL server, you need an OAuth token that corresponds to the permission.

The steps to create a personal access token from the command line are described here. The permissions you need to access are determined by what type of data you request. For example, choose User permissions to get the data for your users. If you need to get repository information, select the appropriate repository permissions.

The API notifies you when a resource requires specific permissions.

GRAPHQL Endpoint

The REST API V3 has multiple endpoints, and the GRAPHQL API V4 has only one endpoint:

https://api.github.com/graphql

Regardless of what you do, the endpoints remain fixed.

Communication with GRAPHQL

In rest, the HTTP verb determines what action to take. In graphql, you need to provide a JSON-encoded request body to tell you whether to execute query or mutation, so the HTTP verb is post. The introspection query is an exception, it is just a simple get request to the endpoint.

About query and mutation operations

There are two actions in the GitHub GRAPHQL API: Query and mutation. The graphql analogy for the rest,query operation is similar to a GET request, mutation operation is similar to Post/patch/delete. Mutation Mame decides which changes to perform.

Query and mutation have a similar form, but there are some important differences.

About Query

GRAPHQL query will only return the data you specified. To create a query, you need to specify "field within Fields" (or nested internal fields) until you return only scalars.

The structure of query is similar:

query {  JSON objects to return}

About mutation

To create a mutation, you must specify three things:

    1. Mutation Name: The type of modification you want to perform
    2. Input object: The data you want to pass to the server is made up of input field. Pass it as argument to mutation name
    3. Payload object: The data that you want the server to return to you, consisting of the return field. Pass it as body of mutation name

The structure of the mutation is similar:

mutation {  mutationName(input: {MutationNameInput!}) {    MutationNamePayload}

In this example, the input object is Mutationnameinput,payload object for Mutationnamepayload.

Using variables

Variables makes query more dynamic and powerful, while simplifying the value of mutation input object.

The following is an example of a single-valued variables:

query($number_of_repos:Int!) {  viewer {    name     repositories(last: $number_of_repos) {       nodes {         name       }     }   }}variables {   "number_of_repos": 3}

The use of variables is divided into three steps:

    1. Define variables outside the operation through a variables object:
variables {    "number_of_repos": 3 }

The object must be a valid JSON. There is only one simple int variable type in this example, but in practice you might define more complex types of variables, such as input object. You can also define multiple variables.

    1. To pass a variable as an argument incoming operation:
query($number_of_repos:Int!){

argument is a key-value pair, the key is the variable name (such as $number_of_repos) that starts with a value, which is a type (such as int). If the type is required, add!. If you define multiple variables, include them in the form of multiple parameters.

    1. To use variables in an operation:
repositories(last: $number_of_repos) {

In this example, we use variables instead of getting the number of repositories. In the 2nd step we specify the type because GRAPHQL enforces the use of strongly typed.

This process allows the request parameters to become dynamic. Now we can simply change the value in the variables object and keep the rest of the request intact.

Using variables as argument allows you to dynamically update the values in the variables without changing the request.

Demonstration cases

query Example

Let's complete a more complex query.

The following query finds the Octocat/hellow-world repository, finds the last 20 closed issue, and returns the title, URL, and top 5 tags for each issue:

query {  repository(owner:"octocat", name:"Hello-World") {    issues(last:20, states:CLOSED) {      edges {        node {          title          url          labels(first:5) {            edges {              node {                name              }            }          }        }      }    }  }}

Let's look at each section in one line:

query {

Because we want to read from the server instead of modifying the data, the root operation is query. (Default to query if you do not specify an action)

repository(owner:"octocat", name:"Hello-World") {

To start our query, we want to find the Repository object. Schema validation indicates that the object requires the owner and name parameters

issues(last:20, states:CLOSED) {

To calculate all issue for this repository, we request the issue object. (We can request a separate issue in a repository, but this requires that we know what I need to return the serial number of the issue and provide it as a argument.) )

Some details of the issue object:

      • According to the document, the object type is Issueconnection
      • The schema check indicates that the object requires a result of the last or first value as argument, so we provide 20
      • The document also tells us that the object accepts an states argument, which is a Issuestate enumeration type that accepts an open or closed value. In order to find only the closed issue, we give the states key a closed value.
edges {

We know that issues is a connection, because its type is issueconnection. To get the data for a single issue, we need to get node through edges.

node {

We get node from the end of edge. The Issueconnection document indicates that node at the end of the Issueconnection type is a issue object.

Now that we know we're going to get a issue object, we can look up the document and specify the field we want to return:

titleurllabels(first:5) {  edges {    node {      name    }  }}

We specify the title,url,labels of the issue object.

Labels field type is labelconnection. As with the issue object, since labels is a connection, we must traverse its edge to reach the connected Node:label object. On node, we can specify the Label object field that we want to return, in this case name.

You may have noticed that running this query in the Octocat public repository Hellow-world does not return many labels. Try running it in your own label repository, and you'll see the difference.

mutation Example

Mutation often requires you to get the request information by executing query first. This example has two actions:

    1. Get issue ID by query
    2. Add a emoji expression to issue by mutation
query FindIssueID {  repository(owner:"octocat", name:"Hello-World") {    issue(number:349) {      id    }  }}mutation AddReactionToIssue {  addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {    reaction {      content    }    subject {      id    }  }}
It is not possible to execute a mutation while executing a query, and vice versa.

Let's look at this example again. The goal looks simple: Add a emoji expression to a issue.

So how do we know that we need a query first? We don't know yet.

Because we want to change the data on the server (add a emoji to issue), we first look for useful mutation from the schema. The document shows a mutation of Addreaction, described as: Adds a reaction to a subject. Very good!

The mutation documentation lists three input field:

    • Clientmutationid (String)
    • Subjectid (id!)
    • Content (reactioncontent!)

! Indicates that Subjectid and content are required. Content is necessary to understand: we want to add an expression, we must indicate which emoji to use.

But why is Subjectid necessary? Because Subjectid is the only way to indicate which issue in the repository to add emoticons to.

That's why in the example you first have to have a query: to get the ID.

Let's look at this query in one line:

query FindIssueID {

Here we execute a query, and we name it Findissueid. Naming query is a non-essential.

repository(owner:"octocat", name:"Hello-World") {

We specify a repository by querying the Repository object and passing in the owner and name two argument.

issue(number:349) {

We specify the issue to add emoticons by querying the issue object and passing in Numberargument.

id

This is what we Github.com/octocat/hellfrom https://o-world/issues/349 Gets and passes the ID as the Subjectid.

When we execute this query, we can get id:mdu6sxnzdwuymzezote1nte=.

NOTE: The ID returned from query is the value we are going to pass as Subjectid in mutation. The document and schema introspection do not indicate this relationship; you need to understand the concepts behind these names to make it clear.

Knowing the ID, we can do the mutation:

mutation AddReactionToIssue {

Here we execute a mutation and name it addreactiontoissue. As with query, naming a mutation is not necessary.

addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {

Let's see this line.

      • Addreaction is the name of mutation.
      • Input is the required argument key. For mutation, this key is always input.
      • {subjectid: "mdu6sxnzdwuymzezote1nte=", Content:hooray} is the desired argument value. This value is always input object (and therefore the parentheses) that are composed of input field (Subjectid and content in this case).

How do we know which value is used in content? The Addreaction document tells us that the Contentfield type is reactioncontent, which is an enumeration type because GitHub's issue only supports part of the emoji expression. The document lists the allowable values (note that some of the values differ from the corresponding emoji names):

      • Thumbs_up
      • Thumbs_down
      • LAUGH
      • Hooray
      • Confused
      • Heart

The remainder of the request consists of the payload object. Here we indicate the data that we want the server to return after executing mutation. These lines are obtained from the Addreaction document and can return three field:

      • Clientmutationid (String)
      • Reaction (reaction!)
      • Subject (reactable!)

In this example, we return two required field (reaction and subject), both of which have the required internal field (content and ID, respectively).

When we execute mutation, the return result is as follows:

{  "data": {    "addReaction": {      "reaction": {        "content": "HOORAY"      },      "subject": {        "id": "MDU6SXNzdWUyMTc5NTQ0OTc="      }    }  }}

One last thing: When you pass mutation field in input object, the syntax can be stiff. This can be improved by placing the field in the variable. Here's how to rewrite the original mutation with variable:

mutation($myVar:AddReactionInput!) {  addReaction(input:$myVar) {    reaction {      content    }    subject {      id    }  }}variables {  "myVar": {    "subjectId":"MDU6SXNzdWUyMTc5NTQ0OTc=",    "content":"HOORAY"  }}
you may notice that the content in the previous example (used directly in mutation) is not quoted outside of Hooray, but is quoted when used in variable. The reasons are as follows:
    • When content is used directly in mutation, the schema expects the value type to be reactioncontent, which is an enumeration type instead of a string. If you add quotation marks outside the enumeration type, the schema throws an error because the quotation marks represent the string.
    • When content is used directly in variable, the variables contents must be valid JSON, so the quotation marks are required. The schema checksum is correctly interpreted as a reactioncontent type when variable is passed into mutation during execution.

Documentation Guidelines

On the GitHub developer site, there is a web-based interface document for developers to query, but I do not recommend that you query the interface in this way.

Traditional REST API as a server resource or database data mapping, its structure can be understood as a form of a list, so through the document directory can be easily queried. GRAPHQL API from the name can be seen in its internal use of a similar "graph" data structure to reflect the complexity of the relationship between nodes. It is difficult to understand the interface in a comprehensive way by reading the document from beginning to finish.

GitHub provides developers with a tool called Explorer :

With the developer's own GitHub account authorization, you can use this tool to easily test various requests for the GitHub GRAPHQL API. At the same time, the sidebar on the right allows you to easily search or link to the required API documentation. With this combination of experimentation and documentation, you can see the connection relationships and query requirements for each object in a way that graphql thinking.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.