Installation steps:

1.npm install

2. Install and connect the database

Conf /db.js /graphql.sql

3. Startup procedure

npm start

4. Visit:

localhost:3003

View related interface access through developer tools

5. Access the debugging tool:

http://localhost:3003/graphql

http://localhost:3003/article

6. The official simple version

/app_simple.js

7. Minimum implementation version of Schame

/graphql/user/userSchame.js

What is GraphQL

GraphQL is an application-level query language developed by Facebook in 2012 and open source in 2015. You define a graphQL-based pattern in the background, and then your clients can query the data they want, without having to redefine an interface to return the data you need.

Because you don’t need to change your background, this approach is better than the REST API approach and gives you the flexibility to change the data display on different clients.

GraphQL is a specification. This means you can implement GraphQL in any language. Click here to see more about GraphQL. Facebook has a GraphQL implementation for JavaScript.

Why use it

GraphQL provides an easy-to-understand set of complete descriptions of the data in your API, enabling a client to get exactly what it needs without any redundancy, making it easier for the API to evolve over time, and for building powerful developer tools. Get multiple resources with one request

  1. Declarative. The format of the results describing all possible types of system queries is determined by the requester (that is, the client) rather than the responder (that is, the server). You don’t need to write a lot of extra interfaces to accommodate client requests

  2. Reduce the maintenance workload of development documents, and correspondingly reduce communication costs

  3. Strongly typed. Each GraphQL query must follow its set type to be executed.

  4. Requests to merge multiple interfaces can be combined into one

  5. Ask for the data you want no more, no less

How to use

introspection

http://localhost:3003/graphql

GraphQL is introspective, which means you can query a GraphQL to know its own schema details.

Query __schema to list all types defined in that schema and get the details for each:

query {
  __schema {
    types {
      name
      kind
      description
      fields {
        name
      }
    }
  }
}
Copy the code

Query __type for details of any type:

query {
  __type(name: "Repository") {
    name
    kind
    description
    fields {
      name
    }
  }
}
Copy the code

Tip: Introspection queries are probably your only GET requests in GraphQL. Whether it's query or mutation, the GraphQL request should be POST if you want to pass the request body

The query

List query (no parameters)

{
	courses {
    id
	  score
	  course
	}
}
Copy the code

Results:

{" data ": {" courses" : [{" id ": 1," score ": 33," course ":" mathematics "}, {" id ": 2," score ": 55," course ":" the language "}, {" id ": 3, "score": 55, "course": "math"}]}Copy the code

### separate query (with parameters)

{
	course(id:1) {
	  score
	  course
	}
}
Copy the code

Results:

{" data ": {" course" : {" score ": 33," course ":" mathematics "}}}Copy the code

change

mutation {
  addUser (name:"nk",sex:"22",intro:"sdfasdfasdf"){
  id
  }
}

Copy the code

Results:

{
  "data": {
    "addUser": {
      "id": 26
    }
  }
}Copy the code

Combination query

{
	courses {
    id
	  score
	  course
	}
  users {
    id
    name
  }
}
Copy the code

The results of

{" data ": {" courses" : [{" id ": 1," score ": 33," course ":" mathematics "}, {" id ": 2," score ": 55," course ":" the language "}], "users" : [ { "id": 1, "name": "xiaoming" }, { "id": 2, "name": "2" }, { "id": 3, "name": "2333" } ] } }Copy the code

Query the alias

Sometimes we want to look like this to separate the data so that we can call it in different places:

{
  postsnoargs{
    title
  },
  postsnoargs{
    _id
  }
}Copy the code

Here’s what we’re imagining:

{
  "data": {
    "postsnoargs": {
    		"title":[
    			"title": "Sharing the Meteor Login State Between Subdomains",
    		],
    		"_id":[
    			"_id": "0176413761b289e6d64c2c14a758c1c7"
    		]
    }
   }
}Copy the code

But the server actually returns something like this:

{
  "data": {
    "postsnoargs": [
      {
        "title": "Sharing the Meteor Login State Between Subdomains",
        "_id": "0176413761b289e6d64c2c14a758c1c7"
      }
    ]
  }
}Copy the code

We need to set the alias, otherwise the server will return to merge your data:

{
  posttitle:postsnoargs{
    title
  },
  postid:postsnoargs{
    _id
  }
}Copy the code

The server returns:

{
  "data": {
    "posttitle": [
      {
        "title": "Sharing the Meteor Login State Between Subdomains"
      }
    ],
    "postid": [
      {
        "_id": "0176413761b289e6d64c2c14a758c1c7"
      }
    ]
  }
}Copy the code
 query {
	corsesssssss:courses {
    id
	  score
	  course
	}
  users {
    id
  }
}Copy the code

Query the user input type

mutation {
  addUserByInput (userInfo:{
    name:"222222",
    intro:"33",
    sex:"2"
  }) {
    id
  }
}

Copy the code

Results:

{
  "data": {
    "addUserByInput": {
      "id": 27
    }
  }
}Copy the code

How to pass arguments to call the GraphQL API

// (unit:cm)

{
  user(id: 0) {
    name
    stature(unit: MM)
    intro
    id
  }
}Copy the code

Nested query

http://localhost:3003/article

Sometimes we need to filter the queried data, such as limiting the size, and we need a nested query to do this.

For example, the following query starts with A national province information:

{
  address(nameKey:"A"){
    ShortKey,
    Content(limit:5) {
      Id,
      Code,
      Name,
      FirstStr
    }
  }
}Copy the code

The server returns:

{" data ": {" address" : [{" ShortKey ":" A ", "Content" : [{" Id ": 36," Code ":" 152900 ", "Name" : "la shan union", "FirstStr" : "A"}, {" Id ": 39," Code ":" 210300 ", "Name" : "anshan city", "FirstStr" : "A"}, {" Id ": 105," Code ":" 340800 ", "Name" : "Anqing city," "FirstStr" : "A"}, {" Id ": 155," Code ":" 410500 ", "Name" : "anyang city", "FirstStr" : "A"}, {" Id ": 293," Code ": "513200", "Name" : "aba Tibetan and qiang autonomous prefecture," "FirstStr" : "A"}}}}]]Copy the code

The Content field limits the return of the top five markets. Note that the limit is set by the server, not the Graphql keyword.

Back-end parse queries

graphql(schema, ' query HeroNameAndFriends{\n' +
        '\tcourses {\n' +
        '    id\n' +
        '\t  score\n' +
        '\t  course\n' +
        '\t}\n' +
        '}', root).then((response) => {
        console.log(response);
    });
Copy the code

shard

http://localhost:3003/article

In GraphQL, a fragment is a fragment that can be reused.

If we need to query information about three different articles, we might do the following query:

{
  first:posts(index:1){
    title,
    category,
    layout
  },
  second:posts(index:2){
    title,
    category,
    layout
  },
  third:posts(index:3){
    title,
    category,
    layout
  }
}Copy the code

We ran the above posts query over and over again, and it might not seem like much at first, but when the data you need to query has dozens of fields, you start to get a headache (trust me).

So what are some ways that we can reuse this piece that we use a lot?

Let me give you the answer:

fragment post on Post{
  title,
  category,
  layout
}Copy the code

The above is a shard,Post is a server defined type, you can look at the document in the upper right corner, each operation name will have a return type.

Let’s start with this shard:

{ first:posts(index:1){ ... post }, second:posts(index:2){ ... post }, third:posts(index:3){ ... post } } fragment post on Post{ title, category, layout }Copy the code

Using object expander… If you’re familiar with ES6, you’ll be particularly familiar with this, so could we try something similar in ES6?

Let’s try:

{ first:posts(index:1){ ... post }, second:posts(index:2){ ... post, category }, third:posts(index:3){ ... post, layout } } fragment post on Post{ title, category, }Copy the code

It doesn’t seem to be a problem at all, the server is returning the correct information, I won’t explain this, it is all ES6 stuff, if you don’t understand ES6 then you should hurry up.

Shard summary

Shards can also be nested, so you can write shards for any data type defined by the server, which greatly reduces the time you spend writing duplicate code.

Query variable

As mentioned above, sharding can save a lot of time, so now I’m going to talk about query variables that can increase your life (ok, I admit I’m pulling my hair out).

For the query with parameters above, we queried the data when index equals 1,2, and 3. Sharding reduces the time you need to enter the same field, and query variables reduce the time you need to write the shard…

How much nonsense fill, first look at the code:

query getFewPosts($index: Int!) { first:posts(index:$index){ ... post } } fragment post on Post{ title, category, }Copy the code

Then enter in the query window:

{
	"index":1
}Copy the code

This is a simple variable query that can also be used with sharding. You can add several variables to increase the use of sharding:

query getFewPosts($index: Int! , $index1: Int! , $index2: Int!) { first:posts(index:$index){ ... post }, second:posts(index:$index1){ ... post, category }, third:posts(index:$index2){ ... post, layout } } fragment post on Post{ title, category, }Copy the code

Then enter in the query window:

{
  "index": 1,
  "index1": 2,
  "index2": 3
}Copy the code

Front-end query:

var xhr = new XMLHttpRequest(); xhr.responseType = 'json'; xhr.open("POST", "/article"); xhr.setRequestHeader("Content-Type", "application/json"); xhr.setRequestHeader("Accept", "application/json"); xhr.onload = function () { console.log('data returned:', xhr.response); } xhr.send(JSON.stringify({ query: ` query getFewPosts($index: Int! , $index1: Int! , $index2: Int!) { first:posts(index:$index){ ... post }, second:posts(index:$index1){ ... post, category }, third:posts(index:$index2){ ... post, layout } } fragment post on Post{ title, category, } `, variables:{ "index": 1, "index1": 2, "index2": 3 } }));Copy the code

How is the server implemented

Simple way (app_simple.js)

var express = require('express'); var graphqlHTTP = require('express-graphql'); var { GraphQLList, GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLInt, GraphQLFloat, GraphQLEnumType, GraphQLNonNull, GraphQLInterfaceType, GraphQLInputObjectType, GraphQLUnionType } = require('graphql'); Var animals=[{chinaName: 'dog ', legs: 4}, {englishName: 'fish', tailColor:'red'},]; // define schema and resolver const Dog = new GraphQLObjectType({name: 'Dog', description: 'Dog entity ', fields: () => ({chinaName: {type: new GraphQLNonNull(GraphQLString)}, legs: {type: new GraphQLNonNull(GraphQLInt)}, }), isTypeOf:obj=>obj.legs, }); Const Fish=new GraphQLObjectType({name:'Fish', description:" Fish entity ", fields: () => {return ({englishName: {type: new GraphQLNonNull(GraphQLString)}, tailColor: {type: new GraphQLNonNull(GraphQLString)}, }); }, isTypeOf:obj=>obj.tailColor, }); const Animal = new GraphQLUnionType({ name: 'Animal', description: 'Union', types:[Dog,Fish], resolveType:function (obj) { if(obj.legs) { return Dog; }else if(obj.tailColor){ return Fish; }else{ return null; }}}); Const Query=new GraphQLObjectType({name:'AnimalQuery', description:' AnimalQuery', Fields ()=>({animals:{type:new GraphQLList(Animal), description:' Query all animals ', resolve:function () {return animals; }}})}); const schema = new GraphQLSchema({ types: [Dog, Fish,Animal], query: Query }); var app = express(); App. use('/graphql', graphqlHTTP({schema: schema, graphiQL: true, // enable graphiQL})); App.listen (4000, () => console.log(' localhost:4000/graphql'));Copy the code

The GraphQL has the corresponding JavaScript type:

GraphQLObjectType,// custom type GraphQLSchema,// Define view GraphQLInterfaceType,// describe multiple types of generic field GraphQLList,// other types of encapsulation GraphQLString,// String type GraphQLInt,// integer float,// float type GraphQLEnumType,// iterable type GraphQLNonNull,// null-not allowed, accepts a GraphQL typeCopy the code

Define a query

Const Post = new GraphQLObjectType({name:"Post", description:" an article ", Fields ()=>({_id:{type:new GraphQLNonNull(GraphQLString),// null is not allowed}, Title :{type:new GraphQLNonNull(GraphQLString),// can't be empty}, category:{type:GraphQLString}, layout:{ type:GraphQLString }, content:{ type:GraphQLString }, }) });Copy the code

An article contains the id, title, category, layout, and the content of these information, the empty string is not allowed in the id and title, if the query to the data without the two would be an error.

Once defined, we need to create a reference in the root query, otherwise the definition will not be used:

Const Query = new GraphQLObjectType({name: 'BlogSchema', description: 'Root of the Blog Schema', fields: () => ({// echo: {//... }, // Post query posts:{type:new GraphQLList(Post), args:{index:{type:GraphQLInt}}, Resolve :(source,args)=>{return [PostsList[args.index]],// return array (although only one)}}}); })Copy the code

The article query posts receives an index parameter, which is an integer.

Resolve returns the corresponding article information stored in the PostsList array, because posts returns an array (all the data in the array is Post objects), and the query is a Post object, so it needs to be enclosed in an array number.

Sometimes you need to nest severalGraphQLObjectTypeFor example, schema.js in the project defines an address query and three layers of query.

Mutation

Sometimes when the client queries the data, it is also accompanied by modifying the data and creating the data, so here we also introduce how to update the data.

Let’s look at a Mutation operation:

Mutation CREATE{createAddress(Id:1,Code:"13156", FirstStr:"S"){Id, Name, Code,}}Copy the code

Add a prefecture level city with the following fields :Id,Code,Name,FirstStr.

CREATE is a mutation name, not a keyword, so you can use any other name you like.

CreateAddress is a keyword defined by the server that accepts four fields, with the created information returned in curly braces.

Let’s look at the server side:

Const Mutation = new GraphQLObjectType({name:"Mutation", description:" add/delete data ", fields:()=>({ createAddress:{ type:AddressContent, args:{ Id:{ type:new GraphQLNonNull(GraphQLInt) }, Code:{ type:new GraphQLNonNull(GraphQLString) }, Name:{ type:new GraphQLNonNull(GraphQLString) }, FirstStr:{ type:new GraphQLNonNull(GraphQLString) } }, resolve:(source,args)=>{ let address = Object.assign({},args); / / get the data / / to uppercase address. FirstStr = address. FirstStr. The toUpperCase (); let queryData = _.find(AddressList,item=>item.ShortKey===address.FirstStr); If (queryData){// If (queryData){// If (queryData.content.push (address); // console.log(address) return address; } else{return null; }}}})})Copy the code

todoList

  1. Learn to use DataLoader to get list data

  2. Advanced usage interface federation, etc

# Related documents:

Official Video Tutorial

GraphQL series is a quick start tutorial

GraphQL series two data types

GraphQL series 3 JavaScript basics

This series is better

What the devil GraphQL

GraphQL exploration of node.js server practice

GraphQL with Koa Best Introductory practices

Basic set of implementation, but no database, can not run through

GraphQL: From REST to GraphQL, a more complete data query definition

GraphQL: An interface style that differs from REST

Github: github.com/zhaiqianfen… Github.com/proYang/Gra… The KOA implementation documentation is good and the package is good. Pretty good ### pit

The node support import

Create a new start.js file in your project folder and write the following code inside:

require('babel-core/register')({
  'presets': [
    'stage-3',
    ["latest-node", { "target": "current" }]
  ]
})

require('babel-polyfill')
require('./server')
Copy the code

Then, from the command line, run NPM install babel-core babel-polyfill babel-preset-latest-node babel-preset-stage-3 –save-dev to install a few development modules.

Once installed, run Node start.js from the command line

mysql

1. Async awit problem between graphQL and mysql database query