前言
上节课,我提到想直接使用线上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
时,限制用户必须传入某些参数才能成功等等其他相关知识