A blog portal using SpringBoot to build the GraphQL interface project

This blog post is about the use of Express to build the GraphQL interface project in NodeJS

hello world

mkdir graphql-js-demo
cd graphql-js-demo
npm init
yarn add express express-graphql graphql
Copy the code

Create file server.js to add the following code

const express = require("express");
const graphqlHTTP = require("express-graphql");
// const schema = require("./schema/schema");

var { buildSchema } = require("graphql");

// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
  type Query {
    hello: String
  }
`);

// The root provides a resolver function for each API endpoint
var root = {
  hello: () => {
    return "Hello world!";
  }
};

const app = express();
app.use(
  "/graphql",
  graphqlHTTP({
    schema: schema,
    rootValue: root,
    graphiql: true
  })
);
app.listen(4000);
console.log("Running a GraphQL API server at http://localhost:4000/graphql");
Copy the code

Start the

node server.js
Copy the code

Input browser visit http://localhost:4000/graphql

{
  hello
}
Copy the code

Click Run and you get the result

{ "data": { "hello": "Hello world!" }}Copy the code

Code from the official website graphql.org/graphql-js/…

Create schema

Above is just a hello world small program, output is also a static string, there is no data query, association, etc

Graphql is built by SpringBoot in a blog post that gives a general idea of how to run graphQL

  1. Define a schema, or data structure
  2. Define query methods, query methods to deal with data query and associated query logic

Define a schema create a folder schema In this folder create a file schema.js that defines schemas and query methods

Because it involves simulating query data, you’ll need to install LoDash

yarn add lodash
Copy the code
const graphql = require("graphql"); const _ = require("lodash"); const { GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLID, } = graphql; / / simulation data const books = [{id: "1", the name: "Java,"}, {id: "2", the name: "spring",}]. Const BookType = new GraphQLObjectType({name: "Book", fields: () => ({id: {type: GraphQLID}, name: { type: GraphQLString }, }) }); // Define query method const RootQuery = new GraphQLObjectType({name: "RootQueryType", fields: {book: {type: BookType, args: { id: { type: GraphQLID } }, resolve(parent, args) { return _.find(books, { id: args.id }); } } books: { type: new GraphQLList(BookType), resolve(parent, args) { return books; }}}}); Module.exports = new GraphQLSchema({query: RootQuery});Copy the code

Modify the contents of server.js

const express = require("express");
const graphqlHTTP = require("express-graphql");
const schema = require("./schema/schema");

const app = express();
app.use(
  "/graphql",
  graphqlHTTP({
    schema: schema,
    graphiql: true
  })
);
app.listen(4000);
console.log("Running a GraphQL API server at http://localhost:4000/graphql");
Copy the code

The article chain: tomoya92. Dead simple. IO / 2019/05/31 /…

Start the service and query the result as shown

Adding associated

We have the book, and now we add the Author of the book, Author

The association relationship is that the book data will have an authorId field, which represents the ID of the Author associated with the book, and then define an Author information in BootType, and then handle the query logic

const BookType = new GraphQLObjectType({ name: "Book", fields: () => ({ id: { type: GraphQLID }, name: { type: GraphQLString}, // define an author object to query the author information according to the authorId in the book author: {type: AuthorType, resolve(parent, args) {// Resolve (parent, args) AuthorType, resolve(parent, args) { Return _. Find (authors, {id: parent. AuthorId}); }}})});Copy the code

The complete code is as follows

const graphql = require("graphql"); const _ = require("lodash"); const { GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLInt, GraphQLID, } = graphql; const books = [ { id: "1", name: "java", authorId: "2" }, { id: "2", name: "spring", authorId: "3" }, { id: "3", name: "nodejs", authorId: "1" }, { id: "4", name: "python", authorId: "2" }, { id: "5", name: "swift", authorId: "1" }, { id: "6", name: "hibernate", authorId: "3" } ]; const authors = [ { name: "tomcat", age: 12, id: "1" }, { name: "jetty", age: 22, id: "2" }, { name: "maven", age: 21, id: "3" } ]; const BookType = new GraphQLObjectType({ name: "Book", fields: () => ({ id: { type: GraphQLID }, name: { type: GraphQLString }, author: { type: AuthorType, resolve(parent, args) { return _.find(authors, { id: parent.authorId }); }}})}); const AuthorType = new GraphQLObjectType({ name: "Author", fields: () => ({ id: { type: GraphQLID }, name: { type: GraphQLString }, age: { type: GraphQLInt }, }) }); const RootQuery = new GraphQLObjectType({ name: "RootQueryType", fields: { book: { type: BookType, args: { id: { type: GraphQLID } }, resolve(parent, args) { return _.find(books, { id: args.id }); } } books: { type: new GraphQLList(BookType), resolve(parent, args) { return books; }}}}); module.exports = new GraphQLSchema({ query: RootQuery });Copy the code

The query result of starting the service is shown in the figure

Associated query

Above the realization of the query book information by the way query book author information, that query the author by the way under the book information also find out how to achieve it?

Book association authors are many to one

On the contrary, it is from one side to check the data of more than one side, like checking the book and checking the author, in AuthorType to achieve a logic of querying the book

The GraphQLList type is used as a GraphQLList type. The GraphQLList type is used as a list type

const { GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLInt, GraphQLID, GraphQLList } = graphql; const AuthorType = new GraphQLObjectType({ name: "Author", fields: () => ({ id: { type: GraphQLID }, name: { type: GraphQLString }, age: { type: GraphQLInt }, books: { type: New GraphQLList(BookType), // Define the type in the new way, You can't specify books as GraphQLList resolve(parent, args) { Return _. Filter (books, {authorId: parent.id}); }}})});Copy the code

Query result of starting the service

If you do not specify the author’s book information when querying the author’s book information, then the logic defined in the AuthorType will not work

The original joint chain: tomoya92. Dead simple. IO / 2019/05/31 /…

Connecting to a Database

Install the mongoose

yarn add mongoose
Copy the code

Modify server. Js

const express = require("express"); const graphqlHTTP = require("express-graphql"); const schema = require("./schema/schema"); const mongoose = require("mongoose"); const app = express(); / / connect to the database mongoose. Connect (" mongo: / / 127.0.0.1 / graphql - js - demo ", {useNewUrlParser: true}); mongoose.connection.once("open", function() { console.log("connected to database!" ); }); app.use( "/graphql", graphqlHTTP({ schema: schema, graphiql: true }) ); app.listen(4000); console.log("Running a GraphQL API server at http://localhost:4000/graphql");Copy the code

Create models

Define the Mongoose model and create the Models folder

book.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const bookSchema = new Schema({
  name: String,
  authorId: String
});

module.exports = mongoose.model("Book", bookSchema);
Copy the code

author.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const authorSchema = new Schema({
  name: String,
  age: String
});

module.exports = mongoose.model("Author", authorSchema);
Copy the code

Modify the schema/schema. Js

Add two methods to add data

const Book = require(".. /models/book"); const Author = require(".. /models/author"); // other code... const Mutation = new GraphQLObjectType({ name: "Mutation", fields: { addAuthor: { type: AuthorType, args: { name: { type: GraphQLString }, age: { type: GraphQLInt } }, resolve(parent, args) { let author = new Author({ name: args.name, age: args.age }); return author.save(); } }, addBook: { type: AuthorType, args: { name: { type: GraphQLString }, authorId: { type: GraphQLString } }, resolve(parent, args) { let book = new Book({ name: args.name, authorId: args.authorId }); return book.save(); }}}}); module.exports = new GraphQLSchema({ query: RootQuery, mutation: Mutation });Copy the code

Start the service by calling the addAuthor addBook methods to save the data


Modify the implementation of other queries, before filtering from static data, now change to check from mongodb, the complete code after modification is as follows

schema/schema.js

const graphql = require("graphql"); const _ = require("lodash"); const Book = require(".. /models/book"); const Author = require(".. /models/author"); const { GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLInt, GraphQLID, GraphQLList } = graphql; const BookType = new GraphQLObjectType({ name: "Book", fields: () => ({ id: { type: GraphQLID }, name: { type: GraphQLString }, author: { type: AuthorType, resolve(parent, args) { return Author.findById(parent.authorId); }}})}); const AuthorType = new GraphQLObjectType({ name: "Author", fields: () => ({ id: { type: GraphQLID }, name: { type: GraphQLString }, age: { type: GraphQLInt }, books: { type: new GraphQLList(BookType), resolve(parent, args) { return Book.find({ authorId: parent.id }); }}})}); const RootQuery = new GraphQLObjectType({ name: "RootQueryType", fields: { book: { type: BookType, args: { id: { type: GraphQLID } }, resolve(parent, args) { return Book.findById(args.id); } }, author: { type: AuthorType, args: { id: { type: GraphQLID } }, resolve(parent, args) { return Author.findById(args.id); } }, books: { type: new GraphQLList(BookType), resolve(parent, args) { return Book.find({}); } }, authors: { type: new GraphQLList(AuthorType), resolve(parent, args) { return Author.find({}); }}}}); const Mutation = new GraphQLObjectType({ name: "Mutation", fields: { addAuthor: { type: AuthorType, args: { name: { type: GraphQLString }, age: { type: GraphQLInt } }, resolve(parent, args) { let author = new Author({ name: args.name, age: args.age }); return author.save(); } }, addBook: { type: AuthorType, args: { name: { type: GraphQLString }, authorId: { type: GraphQLString } }, resolve(parent, args) { let book = new Book({ name: args.name, authorId: args.authorId }); return book.save(); }}}}); module.exports = new GraphQLSchema({ query: RootQuery, mutation: Mutation });Copy the code

Parameter non-null check

Some interface parameters cannot be null. You can check them in graphQL as follows

Add GraphQLNonNull to schema/schema.js and add this judgment to the parameter type of the addAuthor method as follows

const Mutation = new GraphQLObjectType({ name: "Mutation", fields: { addAuthor: { type: AuthorType, args: { name: {type: new GraphQLNonNull(GraphQLString)}, // Determine the non-empty age: {type: new GraphQLNonNull(GraphQLString)}, // Determine the non-empty age: {type: New GraphQLNonNull(GraphQLInt)}, resolve(parent, args) {let author = new author ({name: args. args.age }); return author.save(); }}, addBook: {type: AuthorType, args: {name: {type: new GraphQLNonNull(GraphQLString)}, // Determine non-empty authorId: {type: New GraphQLNonNull(GraphQLString)}, resolve(parent, args) {let book = new book ({name: args. args.authorId }); return book.save(); }}}});Copy the code

Start the service test. An error is reported if non-empty parameters are not passed during the call

reference

  • www.youtube.com/watch?v=DU7…

Tomoya92. Making. IO / 2019/05/31 /…