Skip to content
On this page

QA 问答

一、简答题

1. 简述 Graphql (结合Express )是如何使用的?

  • 运行一个 Express GraphQL 服务器,首先需要安装两个依赖库
    npm install express express-graphql graphql --save
    npm install express express-graphql graphql --save
  • 使用 express 模块来运行一个服务器,然后不再直接调用 graphql 函数进行查询,而是使用 express-graphql 库来构建 GraphQL API 服务器,响应入口端点为 “/graphql” 的 HTTP 请求
js
var express = require('express');
var { graphqlHTTP } = require('express-graphql');
var { buildSchema } = require('graphql');
 
// 使用 GraphQL Schema Language 创建一个 schema
var schema = buildSchema(`
  type Query {
    hello: String
  }
`);
 
// root 提供所有 API 入口端点相应的解析器函数
var root = {
  hello: () => {
    return 'Hello world!';
  },
};
 
var 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');
var express = require('express');
var { graphqlHTTP } = require('express-graphql');
var { buildSchema } = require('graphql');
 
// 使用 GraphQL Schema Language 创建一个 schema
var schema = buildSchema(`
  type Query {
    hello: String
  }
`);
 
// root 提供所有 API 入口端点相应的解析器函数
var root = {
  hello: () => {
    return 'Hello world!';
  },
};
 
var 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');
  • 用以下命令启动该 GraphQL 服务器
node server.js
node server.js

由于我们对 graphqlHTTP 设置 graphiql: true,你可以使用 GraphiQL 工具来手动执行 GraphQL 查询。若使用浏览器浏览 http://localhost:4000/graphql,你会看到一个界面能让你输入查询语句。向 GraphQL 查询 { hello },返回结果为 { data: { hello: 'Hello world!' } }

参考:https://graphql.bootcss.com/graphql-js/running-an-express-graphql-server/

2. 简述 Apollo server 的基本使用。

  • apollo-server是一个在nodejs上构建grqphql服务端的web中间件。支持express,koa ,hapi等框架,根据不同的web框架进行安装。
  • 导入 apollo-server
const { ApolloServer, gql } = require("apollo-server");
const { ApolloServer, gql } = require("apollo-server");
  • 定义 schema 和 resolver
js
// 定义schema
const typeDefs = gql`
  type Query {
    foo: String
  }
`;
// 定义resolver
const resolver = {
  // 所以schema中Query内部的字段都会调用这里的Query对象内部对应的方法
  Query: {
    foo: () => {
      return "bar";
    },
  },
};
// 定义schema
const typeDefs = gql`
  type Query {
    foo: String
  }
`;
// 定义resolver
const resolver = {
  // 所以schema中Query内部的字段都会调用这里的Query对象内部对应的方法
  Query: {
    foo: () => {
      return "bar";
    },
  },
};
  • 创建 GraphQL Server,开启 web 服务
js
const server = new ApolloServer({ typeDefs, resolvers })

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`)
})
const server = new ApolloServer({ typeDefs, resolvers })

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`)
})

3. 从 MongoDB 中获取数据的流程。

  • pollo Server 可以从多给位置获取数据。Apollo提供了一个 DataSource 类,我们可以扩展该类以处理特定类型的数据源的交互逻辑。
  • 连接到数据库可以采用apollo-datasource-mongodb。这个包使用DataLoader进行批处理和每个请求的记忆缓存。它还可以选择(如果您提供 a ttl)共享应用程序级缓存。
  • 使用 apollo-datasource-mongodb 包将 MongoDB 数据映射到 GraphQL 数据层
js
const { MongoDataSource } = require('apollo-datasource-mongodb')

class Users extends MongoDataSource {
  getUser(userId) {
    return this.findOneById(userId)
    // this.model // 访问数据模型对象
  }
  getUsers () {
    return this.model.find()
  }
}

module.exports = Users
const { MongoDataSource } = require('apollo-datasource-mongodb')

class Users extends MongoDataSource {
  getUser(userId) {
    return this.findOneById(userId)
    // this.model // 访问数据模型对象
  }
  getUsers () {
    return this.model.find()
  }
}

module.exports = Users
  • 定义mongoose的数据模型scheme,主要针对数据库的。(不同于GraphQL的scheme,针对客户端用户的)
js
// 08\data-sources\user.js
const mongoose = require('mongoose')

const userSchema = new mongoose.Schema({
  name: String,
  age: Number
})

module.exports = mongoose.model('User', userSchema)
// 08\data-sources\user.js
const mongoose = require('mongoose')

const userSchema = new mongoose.Schema({
  name: String,
  age: Number
})

module.exports = mongoose.model('User', userSchema)
  • 使用mongoose进行数据的管理
js
// 08\models\index.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/test', {
  useNewUrlParser: true,
  useUnifiedTopology: true
})

const db = mongoose.connection
db.on('error', console.error.bind(console, 'connection error:'))
db.once('open', function () {
  // we're connected!
  console.log('连接数据库成功')
})

module.exports = {
  User: require('./user')
}
// 08\models\index.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost/test', {
  useNewUrlParser: true,
  useUnifiedTopology: true
})

const db = mongoose.connection
db.on('error', console.error.bind(console, 'connection error:'))
db.once('open', function () {
  // we're connected!
  console.log('连接数据库成功')
})

module.exports = {
  User: require('./user')
}
  • ApolloServer中使用,在创建 server 时,传入 dataSources 选项
js
// 1. 定义 schema
const typeDefs = gql`
  type User {
    _id: ID!,
    name: String!,
    age: Int
  }

  type Query {
    users: [User!]
    user(id: ID!): User
  }
`

// 2. 定义 resolver
const resolvers = {
  // 所有的 Query 都走这里
  Query: {
    async users (parent, args, { dataSources }) {
      const users = await dataSources.users.getUsers()
      return users
    },
    async user (parent, { id }, { dataSources }) {
      const user = await dataSources.users.getUser(id)
      return user
    }
  }
}

const server = new ApolloServer({
  typeDefs,
  resolvers,
  // 任何 GraphQL 请求都会经过这里
  // 该函数接收一个参数:Request 请求对象
  context (req) {
    return { // 返回对象,自定义数据,后续的每个 resolver 都可以直接获取
      foo: 'bar'
    }
  },
  dataSources () {
    return {
      users: new Users(User)
    }
  }
})
// 1. 定义 schema
const typeDefs = gql`
  type User {
    _id: ID!,
    name: String!,
    age: Int
  }

  type Query {
    users: [User!]
    user(id: ID!): User
  }
`

// 2. 定义 resolver
const resolvers = {
  // 所有的 Query 都走这里
  Query: {
    async users (parent, args, { dataSources }) {
      const users = await dataSources.users.getUsers()
      return users
    },
    async user (parent, { id }, { dataSources }) {
      const user = await dataSources.users.getUser(id)
      return user
    }
  }
}

const server = new ApolloServer({
  typeDefs,
  resolvers,
  // 任何 GraphQL 请求都会经过这里
  // 该函数接收一个参数:Request 请求对象
  context (req) {
    return { // 返回对象,自定义数据,后续的每个 resolver 都可以直接获取
      foo: 'bar'
    }
  },
  dataSources () {
    return {
      users: new Users(User)
    }
  }
})

二、代码题

示例用户

{
  "user": {  
    "username": "aaa",
    "email": "aaa@163.com",
    "password": "11111111"
  }
}
{
  "user": {  
    "username": "aaa",
    "email": "aaa@163.com",
    "password": "11111111"
  }
}

查询接口语句

# 注册用户
# mutation createUser($user: CreateUserInput) {
#   createUser(user: $user) {
#     user {
#       email
#       username
#       token
#     }
#   }
# }

# 登录用户
# mutation login($user: LoginInput) {
#   login(user: $user) {
#     user {
#       email
#       username
#       token
#     }
#   }
# }

# 查询当前用户
# query {
#   currentUser {
#     email
#     username
#   }
# }

# 更新用户信息
# mutation updateUser ($user: UpdateUserInput) {
#   updateUser(user: $user) {
#     user {
#       username 
#     	bio
#     }
#   }
# }
     
# 创建文章
# mutation createArticle($article: CreateArticleInput) {
#   createArticle(article: $article) {
#     article {
#       _id
#       title
#       description
#       body
#       author {
#         email
#       }
#     }
#   }
# }

# 获取文章列表
# query {
#   articles (offset: 0, limit: 2) {
#     articles {
#       _id
#       title
#     }
#     articlesCount
#   }
# }

# 查询单个文章
# query {
#   article (id: "631efd1214d14060ccf8ad77") {
#     title
#   } 
# }

# 更新单个文章
# mutation updateArticle($article: CreateArticleInput) {
#   updateArticle(id: "631efd1214d14060ccf8ad77", article: $article) {
#     article {
#       _id
#       title
#       description
#       body
#       author {
#         email
#       }
#     }
#   }
# }

# 删除单个文章
# mutation {
#   deleteArticle(id: "631efe3514d14060ccf8ad80") {
#     article {
#       title
#     }
#   }
# }
# 注册用户
# mutation createUser($user: CreateUserInput) {
#   createUser(user: $user) {
#     user {
#       email
#       username
#       token
#     }
#   }
# }

# 登录用户
# mutation login($user: LoginInput) {
#   login(user: $user) {
#     user {
#       email
#       username
#       token
#     }
#   }
# }

# 查询当前用户
# query {
#   currentUser {
#     email
#     username
#   }
# }

# 更新用户信息
# mutation updateUser ($user: UpdateUserInput) {
#   updateUser(user: $user) {
#     user {
#       username 
#     	bio
#     }
#   }
# }
     
# 创建文章
# mutation createArticle($article: CreateArticleInput) {
#   createArticle(article: $article) {
#     article {
#       _id
#       title
#       description
#       body
#       author {
#         email
#       }
#     }
#   }
# }

# 获取文章列表
# query {
#   articles (offset: 0, limit: 2) {
#     articles {
#       _id
#       title
#     }
#     articlesCount
#   }
# }

# 查询单个文章
# query {
#   article (id: "631efd1214d14060ccf8ad77") {
#     title
#   } 
# }

# 更新单个文章
# mutation updateArticle($article: CreateArticleInput) {
#   updateArticle(id: "631efd1214d14060ccf8ad77", article: $article) {
#     article {
#       _id
#       title
#       description
#       body
#       author {
#         email
#       }
#     }
#   }
# }

# 删除单个文章
# mutation {
#   deleteArticle(id: "631efe3514d14060ccf8ad80") {
#     article {
#       title
#     }
#   }
# }

Released under the MIT License.