What is GraphQL?

GraphQL is both a query language for the API and a runtime for your data queries (from: Official explanation)

GraphQL has its own query syntax, and the API requests it launches tell the server what operations and specific data fields are required by passing query statements. GraphQL defines implementation specifications, and various languages implement GraphQL functional frameworks, through which query syntax can be interpreted and executed. The data is then returned for output to the client


The advantage of GraphQL

All of the following queries and output are from my DEMO, DEMO implementation and source code Github address will be mentioned below

The syntax features meet a variety of needs

  • Support multiple operations: query-> query, mutation-> modify, specification is written before the query statement, default is not written query
  • Support parameters, to achieve a variety of functions, such as: query data, sorting, paging,… … Etc.
  • Syntax Other features, aliases, fragments, define variables, directives,… … Etc.
Query {student(id:86){id name sclass{id num level heads}}Copy the code
{# output "data" : {" student ": {" id" : 86, "name" : "Emma", "sclass" : {" id ": 9," num ": 8," level ": 3," heads ": 68}}}}Copy the code
Update (id: 86, name: "66666") {rt MSG}}Copy the code
{# output "data" : {" update ": {" rt" : 1, "MSG" : "bingo"}}}Copy the code

Query friendliness, query and output correlation

Does the query feel a bit JSON? Query syntax JSON format, the front and back end can be easily used, query statements and output data have a close correlation, through the analysis of query statements to know the output data content fields


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

You can customize the query statement to obtain the required fields, avoiding the output of useless fields and reducing unnecessary data blocks/data field query logic

Many fields

Query {students{ID name classid sclass{ID num level heads}}Copy the code
# {output "data" : {" students ": [{" id" : 19, "name" : "Savannah", "every" : 22, "sclass" : {" id ": 22," num ": 6," level ": 4, "heads": 57 } }, { "id": 34, "name": "Ariana", "classid":33, "sclass": { "id": 33, "num": 3, "level": 4, "heads": 57}}]}}Copy the code

Removed unused field output, less field sclass, you can not conduct sclass data query

Query {students{id name}}Copy the code
{# output "data" : {" students ": [{" id" : 19, "name" : "Savannah"}, {" id ": 34," name ":" Ariana "}]}}Copy the code

API evolution without versioning

API version iteration does not need to distinguish version numbers. Adding fields does not affect existing queries. The request initiator can define the desired query information by himself

# Say No
http://api.xxx.com/student/v1/
http://api.xxx.com/student/v2/
# ... 
Copy the code

Self – check, can query output all definitions

This is a Nice feature of GraphQL service API. It can query the types supported by the GraphQL service API through statements. Development can not spend time writing API documents, GraphQL directly helps developers to quickly understand the API.

{__type(name: "MStudentType") {kind name fields {name description type {name}}}}Copy the code
# {output "data" : {" __type ": {" kind" : "OBJECT", "name" : "MStudentType", "fields" : [{" name ":" id ", "description" : "Student id", "type" : {" name ": null}}, {" name" : "name", "description" : "students", "type" : {" name ": null}}, {" name" : "Age", "description" : "age", "type" : {" name ": null}}, {" name" : "the birthdate", "description" : "birthday", "type" : {" name ": Null}}, {" name ":" sclass ", "description" : "class information", "type" : {" name ":" MClassType "}}]}}}Copy the code

Based on self-inspection, GraphQL has opened source auxiliary tool GraphiQL to facilitate GraphQL interface debugging and automatic generation of interface documents

  • GraphQL helper: GraphiQL enables debugging of query statements and document visualization of the schema defined by the interface
    • Query statement for awareness
    • Error message
    • Statement formatting
    • Execute the query
    • View the schema document information of the interface definition

The graphQL-dotnet open source project’s GraphiQL interface needs to be connected to its own graphQL interface, which requires a few minor tweaks, as discussed later


.net under the introductory tutorial

  • Build the ASP.NET MVC5 WebAPI project
  • NutGet import package
    • GraphQL
    • GenFu, used to initialize test data
  • Simple implementation of a student query API based on GraphQL
    • You can query the student information list
    • You can query information about a student’s class
    • You can query information about a student corresponding to a student ID
    • Student names can be changed

Define mStudent. cs(student), McLass. cs(class), mresult. cs(execution result)

Public class MStudent {/// <summary> /// </summary> public int Id {get; set; } /// <summary> /// Name /// </summary> public string Name {get; set; } /// <summary> /// Age // </summary> public int Age {get; set; } // </summary> // </summary> public int ClassId {get; set; } /// <summary> // birthday /// </summary> public DateTime Birthdate {get; set; } /// </summary> // class /// </summary> public MClass SClass {get; set; } } public class MClass { public int Id { get; set; } /// </summary> /// / </summary> public int Level {get; set; } /// </summary> // </summary> public int Num {get; set; } /// </summary> // </summary> public int Heads {get; set; }} public class MResult {/// <summary> // </summary> public int rt {get; set; } // </summary> // </summary> public string MSG {get; set; }}Copy the code

Defined type GraphType MStudentType, MClassType, MResultType inherit ObjectGraphType TSourceType generics in the corresponding to the data class constructor 】 to add can be queried by Field data fields, including: Description and processing method of field content acquisition, etc

public class MStudentType : ObjectGraphType<MStudent> { private static BStudent _bll { get; set; } public MStudentType() { if (_bll == null) _bll = new BStudent(); Field(d => d.id).description (" student id "); Field(d => d.name).description (" student name "); Field(d => d.age).description (" age "); Field(d => d.birthdate).description (" birthday "); Field<MClassType>("sclass", resolve: d => {if (d.source.sclass! = null) return d.Source.SClass; Var classId = d.ource? .ClassId ?? 0; if (classId > 0) d.Source.SClass = _bll.GetClass(d.Source.ClassId); return d.Source.SClass; },description:" class information "); }} public class MClassType: ObjectGraphType<MClass> {public MClassType() {Field(d => d.level).description (" grade "); Field(d => d.eads).description (" number of people "); Field(d => d.id).description (" id "); Field(d => d.num).description (" class "); } } public class MResultType : ObjectGraphType<MResult> { public MResultType() { Field(d => d.rt); Field(d => d.msg); }}Copy the code

ObjectGraphType: StudentQuery, StudentMutation

public class StudentQuery : ObjectGraphType {public StudentQuery(BStudent BLL) {id Field<MStudentType>("student", arguments: new QueryArguments(new QueryArgument<IntGraphType>() { Name = "id" }), resolve: d => { var id = d.Arguments["id"].GetInt(0, false); return bll.GetModel(id); ; }); // query - ListGraphType<MStudentType>>("students", resolve: d => {return bll.getStudents (); }); } } } public class StudentMutation : ObjectGraphType { public StudentMutation(BStudent bll) { Field<MResultType>("update", arguments: new QueryArguments( new QueryArgument<IntGraphType> { Name = "id" }, new QueryArgument<StringGraphType> { Name = "name" } ), resolve: (d) => { var id = d.Arguments["id"].GetInt(0, false); var name = d.Arguments["name"].GetString(""); If (id <= 0) return new MResult {rt = 0, MSG = "illegal student id"}; If (name.IsNullOrWhiteSpace()) return new MResult {rt = 0, MSG = "invalid name"}; var isSc = bll.UpdateName(id, name); if (! IsSc) return new MResult {rt = 0, MSG = "update failed"}; return new MResult { rt = 1, msg = "bingo" }; }); }}Copy the code

Add an interface to the controller, construct a Schema object, parse and execute the Query results according to the Query conditions, and output Query = StudentQuery, Mutation = StudentMutation

/// </summary> // </returns> [HttpPost] [Route("query")] public object Test_Query() { var r = HttpContext.Current.Request; var query = r.GetF("query"); var bll = new BStudent(); var schema = new Schema { Query = new StudentQuery(bll), Mutation = new StudentMutation(bll) }; var result = new DocumentExecuter() .ExecuteAsync(options => { options.Schema = schema; options.Query = query; }).GetAwaiter(); var json = new DocumentWriter(indent: true).Write(result); return result.GetResult(); }Copy the code

Access the GraphiQL tool

  • Git Clone graphql-dotnet
  • Install the NodeJS environment
  • Command tools CMD open graphql dotnet/SRC/graphql GraphiQL/executing the following command
    • npm install -g yarn
    • yarn install
    • yarn start
  • Run graphql dotnet/SRC/graphql GraphiQL can start: http://localhost:47080/
  • According to own situation to adjust: graphql dotnet/SRC/graphql GraphiQL/app/app. Js script, such as the code posted below
    • Url = GraphQL interface address
    • If the interface address needs to be used in production, the interface address can be passed in as the URL, or the interface address can be entered in the input box
  • After each adjustment, you need to run yarn start again. The front end uses WebPack to package the yarn. Then refresh the page
Import React from 'React '; import ReactDOM from 'react-dom'; import GraphiQL from 'graphiql'; import axios from 'axios'; import 'graphiql/graphiql.css'; import './app.css'; function graphQLFetcher(graphQLParams) { console.log(graphQLParams["query"]); Return axios ({method: "post", url: "http://127.0.0.1:5656/query", / / the window. The location, origin + '/ API/graphql' data: "query=" + graphQLParams["query"], headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(resp => resp.data); } ReactDOM.render(<GraphiQL fetcher={graphQLFetcher} />, document.getElementById('app'));Copy the code

conclusion

  • As for the application, I think we can try to apply it to the requirements of new projects or reconstruct the existing suitable application scenarios. When the service runs stably and gets started, it can be used in a wide range
  • Comparing RestFul to GraphQL, I feel that there is no best protocol, only the most suitable scenario

resources

  • The Demo source code:
    • Demo code to my Gtihub project (GraphQLDemo)
  • Learning materials
    • Zhihu – What is GraphQL
    • GraphQL syntax introduction
    • GraphQL Chinese website
    • How To GraphQL
    • GraphQL with Koa Best Introductory practices

Leave a comment if you have anything to say


Reproduced please state the original address, thank you for your cooperation

Old friends follow my wechat official account of “Big Talk WEB Development” and track my original blog posts

Do not regularly recommend WEB development related technology blog, mutual encouragement and learning exchanges! Qr code left