「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」
前言
上节课,我提到想直接使用线上mlab搭建数据库,但线上mlab一直没法正常登陆(或者好不容易登陆进去,却是cloud mongodb,收费的),所以耽误了这些天,只能选择本地安装mongodb。简单介绍下mongodb本地的安装步骤
- 去官网下载
mongodb的msi包(我的电脑是Win10) - 安装成功之后,它会自动在
C盘的Program Files创建含bin文件的目录,将其添加到系统环境变量里(我选择将data和log文件存储在D盘)
- 在命令行终端,输入
mongod,有输出信息,或者浏览器地址栏输入http://127.0.0.1:27017,看到如下信息,都表明安装已成功
It looks like you are trying to access MongoDB over HTTP on the native driver port.
连接mongodb
在app.js里,添加如下代码
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/admin') // 我使用了本地mongodb的默认admin数据库
mongoose.connection.once('open', () => {
console.log('connected to database')
})
在命令行终端输入$ nodemon server/app.js,看到如下信息,则表明已成功连接数据库
models
之前我们将persons和jobs直接存储在内存中,现在我们需要将它们存储在mongodb里,基于此,我们在项目根目录下创建models文件夹,在该文件夹下,创建两个js文件->person.js以及job.js
person.js的代码如下所示:
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const personSchema = new Schema({
name: String,
sex: String,
age: String,
jobId: String
})
module.exports = mongoose.model("Person", personSchema)
module.exports = mongoose.model("Person", personSchema):创建名为Person的Collection,它里面的数据结构为personSchema对象
我们不需要在里面定义id,因为数据库会自动为每条数据生成id
job.js的代码如下所示:
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const jobSchema = new Schema({
name: String,
department: String
})
module.exports = mongoose.model("Job", jobSchema)
mutation
搭建完models之后,我们需要创建mutation对数据库实现增删改操作,与vuex里的mutation原理类似。我们需要修改schema.js,部分代码如下所示:
const Person = require('../models/person')
const Job = require('../models/job')
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addPerson: {
type: PersonType,
args: {
name: {type: GraphQLString},
sex: {type: GraphQLString},
age: {type: GraphQLInt}
},
resolve(parent, args) {
// Person对应上面的model
let person = new Person({
name: args.name,
sex: args.sex,
age: args.age
})
person.save() // 这是mongoose提供的便利,实例直接调用save方法,可将数据存储在我们指定的数据库内
}
},
addJob: {
type: JobType,
args: {
name: {type: GraphQLString},
department: {type: GraphQLString}
},
resolve(parent, args) {
let job = new Job({
name: args.name,
department: args.department
})
return job.save()
}
},
}
})
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
})
刷新页面http://localhost:4000/graphql,在左侧输入下图命令并运行
很明显,数据已经成功插入,可为何右侧显示"addPerson": null,这是因为我们需要在resolve里返回数据,修改resolve里的代码
resolve(parent, args) {
let person = new Person({
name: args.name,
sex: args.sex,
age: args.age
})
return person.save()
}
再次运行命令,界面如下所示:
执行addJob命令,如下所示:
关联Person和Job
从前文我们可以得知,Person可以关联Job,是通过里面的jobId,现在我们需要知道我们刚刚插入的job数据对应的id是多少,我推荐安装mongodb的图形化管理工具,即MongoDBCompass(官方提供的),方便查看管理数据
MongoDBCompass我下载的是zip压缩文件,解压之后,直接打开.exe文件,连接本地数据库之后,进入到admin数据库,可看到我们刚创建的jobs数据
新建person数据,将上图中的id:61f0bd5de1db61c31d991977与该人关联,修改schema.js,部分内容如下所示:
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addPerson: {
type: PersonType,
args: {
...,
jobId: {type: GraphQLID}
},
resolve(parent, args) {
let person = new Person({
...,
jobId: args.jobId
})
return person.save()
}
},
}
})
刷新页面,执行命令
查看数据库界面,可看到新增后的数据
查询Person所在的Job
为此,我们需要修改Person结构体,代码如下所示:
const Job = require('../models/job')
const PersonType = new GraphQLObjectType({
name: 'Person',
fields: () => ({
id: {type: GraphQLID},
name: {type: GraphQLString},
sex: {type: GraphQLString},
age: {type: GraphQLInt},
job: {
type: JobType,
resolve(parent, args) {
// return _.find(jobs, {id: parent.jobId})
// mongoose提供的model,内置findById、find方法
return Job.findById(parent.jobId)
}
}
})
})
刷新页面,左侧输入以下命令,查询到对应的结果
查询Job所有的persons
我们需要查询某个岗位所有人员,为此,需要重构JobType,代码如下所示:
const JobType = new GraphQLObjectType({
name: 'Job',
fields: () => ({
id: {type: GraphQLID},
name: {type: GraphQLString},
department: {type: GraphQLString},
persons: {
type: new GraphQLList(PersonType),
resolve(parent, args) {
return Person.find({
jobId: parent.id
})
}
}
})
})
通过mutation addPerson增加lisi人员,并将他与jobId: "61f0bd5de1db61c31d991977"关联
再次执行查询,可见该Job岗位有两位人员
schema
schema.js的RootQuery也应做相应的更改,此时查询都应基于model进行find(若参数为空,则查询所有数据)或findById(根据id进行查询),完整的代码如下所示:
const graphql = require('graphql')
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
GraphQLID,
GraphQLInt,
GraphQLList
} = graphql
const _ = require('lodash')
const Person = require('../models/person')
const Job = require('../models/job')
// 创建Person结构体
const PersonType = new GraphQLObjectType({
name: 'Person',
fields: () => ({
id: {type: GraphQLID},
name: {type: GraphQLString},
sex: {type: GraphQLString},
age: {type: GraphQLInt},
job: {
type: JobType,
resolve(parent, args) {
return Job.findById(parent.jobId)
}
}
})
})
const JobType = new GraphQLObjectType({
name: 'Job',
fields: () => ({
id: {type: GraphQLID},
name: {type: GraphQLString},
department: {type: GraphQLString},
persons: {
type: new GraphQLList(PersonType),
resolve(parent, args) {
return Person.find({
jobId: parent.id
})
}
}
})
})
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
person: {
type: PersonType,
args: {
id: {type: GraphQLID}
},
resolve(parent, args) {
return Person.findById(args.id)
}
},
job: {
type: JobType,
args: {
id: {type: GraphQLID}
},
resolve(parent, args) {
return Job.findById(args.id)
}
},
persons: {
type: new GraphQLList(PersonType),
resolve(parent, args) {
return Person.find({})
}
},
jobs: {
type: new GraphQLList(PersonType),
resolve(parent, args) {
return Job.find({})
}
}
}
})
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addPerson: {
type: PersonType,
args: {
name: {type: GraphQLString},
sex: {type: GraphQLString},
age: {type: GraphQLInt},
jobId: {type: GraphQLID}
},
resolve(parent, args) {
let person = new Person({
name: args.name,
sex: args.sex,
age: args.age,
jobId: args.jobId
})
return person.save()
}
},
addJob: {
type: JobType,
args: {
name: {type: GraphQLString},
department: {type: GraphQLString}
},
resolve(parent, args) {
let job = new Job({
name: args.name,
department: args.department
})
return job.save()
}
},
}
})
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
})
结语
今天的课程先到这里,下节课我将为大家介绍,如何在mutation时,限制用户必须传入某些参数才能成功等等其他相关知识