Node.js第四篇:快速上手mongodb
第一章:认识数据库
1.1-为什么要使用数据库
- 动态网站中的数据都是存储在数据库中的,我们要开发动态网站,必须得学会操作数据库。
- 数据库软件可以对数据高效的管理
1.2-什么是数据库
数据库就是存储数据的仓库,可以将数据分门别类的存储。它是独立于语言之外的软件,在后端编程中可以通过相关的API操作数据库。
常见的数据库软件有,oracle、mysql、mongodb等。
在本篇中,我们学习nodejs操作mongodb数据库。
第二章:数据库环境搭建
2.1-下载MongoDB
下载地址:https://www.mongodb.com/download-center/enterprise
2.2-MongoDB安装步骤
第一步:点击下载好的安装包开始安装
第二步:选择同意协议复选框,点击下一步
第三步:选择自定义安装
第四步:自定义安装位置,下一步
第五步:确定数据库服务名称、库文件存储位置、日志位置,下一步
第六步:不要选中数据库可视化工具安装,稍后单独安装,下一步
第七步:安装、完成
2.3-停止和启动数据库服务
以管理员身份打开命令行窗口,数据库服务默认是启动的。
关闭服务命令:net stop mongodb
启动服务命令:net start mongodb
2.4-配置MongoDB环境变量
首先复制mongodb安装包的bin目录路径如下:(具体根据自己的安装目录复制)
C:\Program Files\MongoDB\Server\4.2\bin
其次打开配置环境变量的窗口:
选中【我的电脑】或【此电脑】→鼠标右键点击→【选择属性】→【选择高级系统变量】→【点击环境变量】→【系统变量-Path-编辑】→【新建】→【粘贴复制的mongodb安装包bin目录路径】→【回车添加】→【确定...】
2.5-下载可视化工具
下载地址:https://www.mongodb.com/download-center/compass
2.6-可视化工具安装步骤
第一步:点击下载好的安装包,下一步
第二步:选中安装好的位置,下一步
第三步:安装、完成
2.7-使用可视化工具
第一步:点击打开已经安装好的MongoDb Compass可视化工具,并切换连接数据库方式
第二步:连接数据库
2.8-数据库相关概念
在一个数据库软件中可以包含或创建多个数据库仓库,在每个数据库仓库中可以包含多个数据集合,每个数据集合中可以包含多条文档(具体的数据)
第三章:Node.js操作mongodb
3.1-Node.js连接数据库
使用Node.js操作mongodb,较好的方式是使用mongoose
第三方依赖包
安装命令:npm install mongoose
使用mongoose连接数据库
// 导入安装好的mongoose模块
const mongoose = require('mongoose')
// 调用connect方法连接数据库
mongoose.connect('mongodb://localhost/test02db', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => { console.log('数据库连接成功') })
.catch((err) => { console.log('数据库连接失败') })
/*【备注】
connect方法返回的是promise对象,执行then表示数据库连接成功,执行catch表示数据库连接失败。
地址:mongodb://localhost/test02db 其中:
① mongodb: 固定协议;
② localhost:数据库主机地址。
③ test02db:数据仓库名称;(注意,若数据库中不存在该仓库,则会自动创建该数据库)
*/
在MongoDB中不需要显式创建数据库,如果正在使用的数据库不存在,MongoDB会自动创建。
3.2-创建集合并插入文档
实现步骤
先设定集合规则
const demoSchema = new mongoose.Schema({
字段名称1: 数据类型,
字段名称2: 数据类型
...
})
再创建集合并应用规则
const DemoModel = mongoose.model('集合名称',集合规则)
插入文档
const demo01 = new DemoModel({
字段名称1: 值,
字段名称2: 值,
...
})
demo01.save()
注意:若集合中没有文档时,在可视化工具中看不到数据库和文档,所以需要插入一条数据。
代码
需求:创建一个学生集合,学生有姓名-name、年龄-age、性别-gender字段,并向集合中插入一条数据。
// 导入安装好的mongoose模块
const mongoose = require('mongoose')
// 调用connect方法连接数据库
mongoose.connect('mongodb://localhost/test02db', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => { console.log('数据库连接成功') })
.catch((err) => { console.log('数据库连接失败') })
// 【定义学生集合规则】
const studentSchema = new mongoose.Schema({
name: String,
age: Number,
gender: String
})
// 【创建学生集合并应用规则】
const Student = mongoose.model('student', studentSchema)
// 【向学生集合中插入一条数据】
let stu1 = new Student({
name: '李小明',
age: 10,
gender: '男'
})
stu1.save()
打开可视化工具查看:
3.3-插入文档的其他方式
方式1:
集合变量名.create({字段1:值,字段2:值...},(err,data)=>{
// err 异常对象,若插入成功,err为null
// data 插入成功后的数据
})
方式2:
集合变量名.create({字段1:值,字段2:值...})
.then(data=>{
// data 插入成功后的数据
})
.catch(err=>{
// err 插入失败时的异常对象
})
代码:
// 导入安装好的mongoose模块
const mongoose = require('mongoose')
// 调用connect方法连接数据库
mongoose.connect('mongodb://localhost/test02db', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => { console.log('数据库连接成功') })
.catch((err) => { console.log('数据库连接失败') })
// 定义学生集合规则
const studentSchema = new mongoose.Schema({
name: String,
age: Number,
gender: String
})
// 创建学生集合并应用规则
const Student = mongoose.model('student', studentSchema)
// 【方式1:向学生集合中插入一条数据】
Student.create({
name: '王五',
age: 19,
gender: '男'
}, (err, data) => {
if (err == null) {
console.log('插入后的数据:' + data)
}
})
// 【方式2:向学生集合中插入一条数据】
Student.create({
name: '小花',
age: 12,
gender: '女'
})
.then(data => {
console.log('插入后的数据:' + data)
})
.catch(err => {
console.log(err)
})
输出结果
插入后的数据:
{ _id: 5e9b2206edc866043483508f,
name: '王五',
age: 19,
gender: '男',
__v: 0
}
插入后的数据:
{ _id: 5e9b2206edc8660434835090,
name: '小花',
age: 12,
gender: '女',
__v: 0
}
3.4-向数据库中导入数据
命令行方式:
命令:mongoimport -d 数据库名称 -c 集合名称 --file 要导入的数据文件
如:
mongoimport -d test02db -c test01Collection --file .\user.json
图形界面方式
3.5-查询集合中的文档数据
查询方法:find,返回Promise对象,then方法中获取查询后的结果
集合准备
// 导入安装好的mongoose模块
const mongoose = require('mongoose')
// 调用connect方法连接数据库
mongoose.connect('mongodb://localhost/test02db', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => { console.log('数据库连接成功') })
.catch((err) => { console.log('数据库连接失败') })
// 定义User集合规则
const userSchema = new mongoose.Schema({
name: String,
age: Number,
hobbies: Array,
email: String,
password: String
})
// 创建User集合并应用规则
const User = mongoose.model('users', userSchema)
3.5.1-查询所有
// 【1.查询所有User数据】
User.find().then(data => {
// data是查询后的结果
console.log(data)
})
3.5.2-条件筛选
// 【2.筛选名字为李四的数据】
User.find({name:'李四'}).then(data => {
console.log(data)
})
// 【3.筛选年龄大于10小于50的数据】
// 条件操作符:$lt小于、$gt大于、$ne不等于、$lte小于等于、$gte大于等于、$eq等于
User.find({age:{$lt:50,$gt:10}}).then(data => {
console.log(data)
})
// 【4.查询显示指定字段,和强制不显示指定字段】
// select方法筛选显示的字段,负号“-” 表示不显示指定的字段
User.find().select("name age -_id").then(data => {
console.log(data)
})
3.5.3-查询一个
// 【5. 查询一个数据】
// findOne方法查询一个
User.findOne().select("name age -_id").then(data => {
console.log(data)
})
3.5.4-skip和limit
// 【6. 查询跳过n个显示m个数据】
User.find().skip(2).limit(2).then(data => {
console.log(data)
})
3.5.5-排序
// 【7. 按照指定的字段升序或排序】
// 升序
User.find().sort('age').then(data => {console.log(data)})
// 降序
User.find().sort('-age').then(data => {console.log(data)})
3.5.6-正则筛选
// 【8. 查询名字含有"王"字的用户数据-正则】
User.find({name:/王/}).then(data => {console.log(data)})
3.5.7-$in
的使用
// 【9. 查询hobbies爱好中含有足球的用户数据】
User.find({ hobbies: { $in: ['足球'] } }).then(data => { console.log(data) })
3.6-删除文档数据
查找并删除一个符合条件的数据
// 【1. 查找并删除一个】
User.findOneAndDelete({ name: '狗蛋' }).then(result => {
// 返回删除后的数据
console.log(result)
})
或
// 【2. 删除一个符合条件的数据】
User.deleteOne({ name: '狗蛋' }).then(result => {
// 返回{ n: 1, ok: 1, deletedCount: 1 }
// n表示影响了多少行,ok:1操作正常,deletedCount:2 表示删除了几个
console.log(result)
})
删除所有符合条件的数据
User.deleteMany({ gender: '女' }).then(result => {
// { n: 2, ok: 1, deletedCount: 2 }
// n表示影响了多少行,ok:1操作正常,deletedCount:2 表示删除了几个
console.log(result)
})
3.7-更新文档数据
更新一个
// 更新一个符合条件的数据
// 返回 { n: 1, nModified: 1, ok: 1 }
User.updateOne({ age: { $gt: 10 } }, { age: 600 }).then(result => console.log(result))
更新多个
User.updateMany({ age: { $gt: 10 } }, { age: 600 }).then(result => console.log(result))
3.8-mongoose校验
校验方式
- require 必填项。值是布尔值,
true
表示必填;值也可以是数组[true,'自定义异常提示信息']
- maxlength 字符串最大长度。 如:
maxlength : 10
或maxlength : [10, '自定义异常提示信息']
- minlength 字符串最大长度。 如:
minlength: 6
或minlength: [6, '自定义异常提示信息']
- max 数值最大值。 如:
max: 120
- min 数值最小值。 如:
min: 1
- enum 限定的值。 如:
enum: ['男','女']
- trim 字符串两边的空格。 如:
trim:true
- default 默认值。 如:
default: new Date()
- validate 自定义验证器。 如:
validate:{validator:(val){返回布尔值},message:"自定义异常信息"}
- 返回true,校验通过。否则,校验失败。
- val,表示校验的值
校验规则
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test02db', { useNewUrlParser: true, useUnifiedTopology: true }).then(() => {
console.log('数据库连接成功')
}).catch((err) => {
console.log(err)
})
const teacherSchema = new mongoose.Schema({
name: {
type: String,
required: true, // 此字段“必须有”
maxlength: 6, // 字符串最大长度
minlength: 3, // 字符串最小长度
trim: true // 自动去除字符串两端空格
},
age: {
type: Number,
required: [true, 'age必须填写'], // // 此字段“必须有” 并自定义异常信息
max: 130, // 数字最大值限制
min: 17 // 数字最小值限制
},
level: {
type: String,
required: true,
enum: {
values:['T1', "T2", "T3", "T4", "T5", "T6"],
message:'等级传值不正确'
} // 限制值的选项
},
info: {
type: String,
// 【validate】自定义验证规则
validate: {
validator: (val) => { // validator 校验方法
// val 校验的值
return val.length > 10 && val.length < 30
// 返回true,校验成功;返回false,校验失败;
},
message: '请写入符合规范的内容'
}
},
addDate: {
type: Date,
default: new Date() // 【default】默认值
}
})
const Teacher = mongoose.model('teacher', teacherSchema)
Teacher.create({
name: '张三丰',
age: 19,
level: 'T3',
info: '我是武当祖师,我的名字叫张三丰'
}).then(document => {
console.log(document)
}).catch(err => {
console.log(err)
})
第四章:扩展
4.1-聚合管道
4.1.1-管道的概念
基本概览
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。
这里我们介绍一下聚合框架中常用的几个操作:
$project
:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。$match
:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。$limit
:用来限制MongoDB聚合管道返回的文档数。$skip
:在聚合管道中跳过指定数量的文档,并返回余下的文档。$group
:将集合中的文档分组,可用于统计结果。$sort
:将输入文档排序后输出。$lookup
: 是将每个输入待处理的文档,经过$lookup 阶段的处理,输出的新文档中会包含一个新生成的数组列(户名可根据需要命名新key的名字 )。数组列存放的数据 是 来自 被Join 集合的适配文档,如果没有,集合为空(即 为[ ])
$lookup的基本语法
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
4.1.2-聚合
MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。
MongoDB中聚合的方法使用aggregate()
聚合的表达式:
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
$avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
$push | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
4.1.3-代码
数据准备
连接数据库的文件db.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test03db', { useNewUrlParser: true, useUnifiedTopology: true }).then(() => {
console.log('数据库连接成功')
}).catch((err) => {
console.log(err)
})
module.exports = mongoose
user集合文件userdb.js
创建user集合
const mongoose = require('./db/db')
// 定义集合规则
const userSchema = new mongoose.Schema({
username: {
type: String,
required: [true, 'username必须填写'],
maxlength: [10, 'username长度不能大于10个字符'],
minlength: [2, 'username长度不能小于2个字符']
},
email: {
type: String,
validate: {
validator: (val) => {
var reg = /^\w+@\w+\.\w+$/
return reg.test(val)
},
message: 'email格式错误'
}
},
age: {
type: Number,
required: [true, 'age必须填写'],
max: [120, 'age值不能大于120'],
min: [0, 'age值不能小于0'],
},
gender: {
type: String,
enum: ['男', '女', '保密'],
default: '保密'
},
addTime: {
type: Date,
default: new Date()
}
})
// 创建集合
const User = mongoose.model('user', userSchema, 'user')
module.exports = User
user表中的数据,可自行导入
{"_id":{"$oid":"5e9e5c3c8f76910a383336f1"},"gender":"男","addTime":{"$date":{"$numberLong":"1587436604484"}},"username":"张三","email":"19989892@qq.com","age":{"$numberInt":"10"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e5ccd7469903f68e8842d"},"gender":"女","addTime":{"$date":{"$numberLong":"1587436749313"}},"username":"丽丽","email":"19949842@qq.com","age":{"$numberInt":"16"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e5ccd7469903f68e8842e"},"gender":"女","addTime":{"$date":{"$numberLong":"1587436749313"}},"username":"花花","email":"11981192@qq.com","age":{"$numberInt":"13"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e5ccd7469903f68e8842f"},"gender":"女","addTime":{"$date":{"$numberLong":"1587436749313"}},"username":"百灵","email":"3425672@qq.com","age":{"$numberInt":"14"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e61b6d365b13aa839ad1d"},"gender":"男","username":"李四","email":"43567432@qq.com","age":{"$numberInt":"15"},"__v":{"$numberInt":"0"},"addTime":{"$date":{"$numberLong":"1587513600000"}}}
截图
查询操作
查询代码-查询用户并显示指定的字段
User.aggregate([
{
$project: {
username: 1,
age: 1,
_id: 0,
mail: '$email' // 邮箱字段设置别名
}
}
]).then(result => {
console.log(result)
})
查询代码-按性别分组查询-查询每组的总数量(
$sum
)、平均年龄($avg
)、最大和最小年龄($max
、$min
)、每个分组的邮箱列表($push
)、第一个用户的名字($first
)、最后一个用户的名字($last
)
User.aggregate([
{
$group: {
_id: '$gender',
count: { $sum: 1 },
ageAvg: { $avg: '$age' },
maxAge: { $max: '$age' },
minAge: { $min: '$age' },
email: { $push: '$email' },
firstUserName: { $first: '$username' },
lastUsername: { $last: '$username' }
}
}
]).then(result => {
console.log(result)
})
查询代码-按条件过滤数据-年龄大于10并且降序以及跳过第1条显示后两条数据、字段显示用户名和年龄但不显示id
User.aggregate([
{
$project: {
username: 1, // 1或true表示显示, 0或false表示不显示
age: true,
_id: 0
}
},
{
$match: {
age: { $gt: 10 }
}
},
{
$sort: {age:-1} // 1表示升序, -1表示降序
},
{
$skip: 1
},
{
$limit: 2
}
]).then(result => {
console.log('-----------年龄大于10的数据有S------------')
console.log(result)
console.log('-----------年龄大于10的数据有E------------')
})
4.2-关联查询
4.2.1 常见的关联关系
常见的表(集合)与(集合)之间的关系有
-
1对1,如用户表与简历表。一个用户有一份简历,一份简历属于某一个用户。
-
1对多,如用户表(作者)与文章表。 一个作者可以发布多篇文章。
-
多对多,如老师和学生的关系。 一个老师可以教多个学生。 一个多学可以被多个老师教。
在此,我们主要来讲解1对多和多对多。
4.2.2-一对多
4.2.2.1-如下关系表
如作者表与文章表。 一个作者可以发布多篇文章。
数据截图
4.2.2.2-数据准备和查询
用户集合文件及连接数据库文件同上(聚合管道中的数据)
创建文章集合articledb.js
集合
const mongoose = require('./db/db')
// 定义集合规则
const articleSchema = new mongoose.Schema({
title: {
type: String,
required: [true, 'title必须填写'],
maxlength: [20, 'title长度不能大于20个字符'],
minlength: [1, 'title长度不能小于1个字符']
},
content: {
type: String,
required: [true, 'content必须填写'],
},
author: {
type: mongoose.Schema.Types.ObjectId, // 类型是ObjectId,存放用户集合中某一个数据的id值
ref: 'user', // 和user集合产生关联
required: true
},
addTime: {
type: Date,
default: new Date()
}
})
// 创建集合
const article = mongoose.model('article', articleSchema, 'article')
module.exports = article
数据文件,可自行导入
{"_id":{"$oid":"5e9e5f930e90c72b8c6a9b4e"},"addTime":{"$date":{"$numberLong":"1587437459745"}},"content":"我和我的祖国","title":"祖国","author":{"$oid":"5e9e5ccd7469903f68e8842d"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9eaf4cd365b13aa839ad1e"},"addTime":{"$date":{"$numberLong":"1587437459745"}},"content":"春天在哪里","title":"春","author":{"$oid":"5e9e5ccd7469903f68e8842d"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9eaf81d365b13aa839ad1f"},"addTime":{"$date":{"$numberLong":"1587437459745"}},"content":"日出真美,啊","title":"日出","author":{"$oid":"5e9e5ccd7469903f68e8842f"},"__v":{"$numberInt":"0"}}
查询操作
// 导入User集合
const User = require('./dao/userdb')
const mongoose = require('mongoose')
const ObjectId = mongoose.Types.ObjectId
// 导入article集合
const Article = require('./dao/articledb')
// 【查询所有文章信息及作者信息】
// populate方法的使用
Article.find().populate('author').then(result => {
console.log(result)
})
// 【查询出指定作者所发布的所有文章】
// $lookup的使用
User.aggregate([
{
$lookup: {
from: 'article',
localField: '_id',
foreignField: 'author',
as: 'articles'
}
},
{
$match: {'_id': new ObjectId('5e9e5ccd7469903f68e8842d')}
}
]).then(data => {
for (var item in data) {
console.log(data[item].articles)
}
})
4.2.3-多对多
4.2.3.1-如下关系表
多对多,如老师表(集合)和学生表(集合)的关系。 一个老师可以教多个学生。 一个多学可以被多个老师教。此时需要中间表。
如下:图解关系表
如下:图解数据关系
4.2.3.2-数据准备和查询
学生集合studentdb.js
const mongoose = require('./db/db')
// 定义集合规则
const studentSchema = new mongoose.Schema({
name: String,
age: Number,
gender: {
type: String,
enum: ['男', '女', '保密'],
default: '保密'
},
addTime: {
type: Date,
default: new Date()
}
})
// 创建集合
const Student = mongoose.model('student', studentSchema, 'student')
module.exports = Student
数据,可导入
{"_id":{"$oid":"5e9e928ed1480c25e4df4032"},"gender":"保密","addTime":{"$date":{"$numberLong":"1587450510415"}},"name":"小明","age":{"$numberInt":"15"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e928ed1480c25e4df4033"},"gender":"保密","addTime":{"$date":{"$numberLong":"1587450510415"}},"name":"小花","age":{"$numberInt":"12"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e928ed1480c25e4df4034"},"gender":"保密","addTime":{"$date":{"$numberLong":"1587450510415"}},"name":"小美","age":{"$numberInt":"14"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e928ed1480c25e4df4035"},"gender":"保密","addTime":{"$date":{"$numberLong":"1587450510415"}},"name":"小啦","age":{"$numberInt":"13"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e928ed1480c25e4df4036"},"gender":"保密","addTime":{"$date":{"$numberLong":"1587450510415"}},"name":"小嘟","age":{"$numberInt":"11"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e928ed1480c25e4df4037"},"gender":"保密","addTime":{"$date":{"$numberLong":"1587450510415"}},"name":"小直","age":{"$numberInt":"16"},"__v":{"$numberInt":"0"}}
老师集合teacherdb.js
const mongoose = require('./db/db')
// 定义集合规则
const teacherSchema = new mongoose.Schema({
name: String,
level: {
type:String,
default:'T8'
},
addTime: {
type: Date,
default: new Date()
}
})
// 创建集合
const Teacher = mongoose.model('teacher', teacherSchema, 'teacher')
module.exports = Teacher
数据,可导入
{"_id":{"$oid":"5e9e9055c0a53c22a81d097b"},"level":"T8","addTime":{"$date":{"$numberLong":"1587449941645"}},"name":"王老师","__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e9055c0a53c22a81d097c"},"level":"T8","addTime":{"$date":{"$numberLong":"1587449941645"}},"name":"张老师","__v":{"$numberInt":"0"}}
中间表集合teacher_studentdb.js
const mongoose = require('./db/db')
// 定义集合规则
const teacher_student_Schema = new mongoose.Schema({
stu_id: {
type: mongoose.Types.ObjectId,
ref: 'student'
},
teacher_id: {
type: mongoose.Types.ObjectId,
ref: 'teacher'
}
})
// 创建集合
const Teacher_student = mongoose.model('teacher_student', teacher_student_Schema, 'teacher_student')
module.exports = Teacher_student
数据,可导入
{"_id":{"$oid":"5e9e93c7dab3653a58cebbf2"},"stu_id":{"$oid":"5e9e928ed1480c25e4df4032"},"teacher_id":{"$oid":"5e9e9055c0a53c22a81d097b"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e93c7dab3653a58cebbf3"},"stu_id":{"$oid":"5e9e928ed1480c25e4df4032"},"teacher_id":{"$oid":"5e9e9055c0a53c22a81d097c"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e93c7dab3653a58cebbf4"},"stu_id":{"$oid":"5e9e928ed1480c25e4df4033"},"teacher_id":{"$oid":"5e9e9055c0a53c22a81d097c"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e93c7dab3653a58cebbf5"},"stu_id":{"$oid":"5e9e928ed1480c25e4df4034"},"teacher_id":{"$oid":"5e9e9055c0a53c22a81d097b"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e93c7dab3653a58cebbf6"},"stu_id":{"$oid":"5e9e928ed1480c25e4df4035"},"teacher_id":{"$oid":"5e9e9055c0a53c22a81d097c"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e93c7dab3653a58cebbf7"},"stu_id":{"$oid":"5e9e928ed1480c25e4df4036"},"teacher_id":{"$oid":"5e9e9055c0a53c22a81d097c"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e93c7dab3653a58cebbf8"},"stu_id":{"$oid":"5e9e928ed1480c25e4df4037"},"teacher_id":{"$oid":"5e9e9055c0a53c22a81d097b"},"__v":{"$numberInt":"0"}}
{"_id":{"$oid":"5e9e93c7dab3653a58cebbf9"},"stu_id":{"$oid":"5e9e928ed1480c25e4df4037"},"teacher_id":{"$oid":"5e9e9055c0a53c22a81d097c"},"__v":{"$numberInt":"0"}}
查询操作
查询出指定老师所教的所有有学生
const mongoose = require('mongoose')
const ObjectId = mongoose.Types.ObjectId
const teacher_studentdb = require('./dao/teacher_studentdb')
const student = require('./dao/studentdb')
teacher_studentdb.aggregate([
{
$lookup: {
from: 'teacher',
localField: 'teacher_id',
foreignField: '_id',
as: 'teacher'
}
},
{
$lookup: {
from: 'student',
localField: 'stu_id',
foreignField: '_id',
as: 'student'
}
},
{
$match: {
teacher_id: new ObjectId('5e9e9055c0a53c22a81d097b')
}
},
{
$project: {
teacher_id: 0,
stu_id: 0,
_id: 0,
__v:0
}
}
]).then(data => {
for (var item in data) {
console.log(data[item].student)
}
})
4.3-Mongodb权限配置
4.3.1-概述
在默认情况下,我们是可以直接连接并操作mongodb数据库的,这样的默认操作时不安全的。
所以,我们需要对mongodb设置权限,也就是说若连接并操作某一个数据库,必须提供用户名和密码才能操作。
4.3.2-Mongodb数据库用户角色
-
数据库用户角色-库使用权限:read、readWrite;
- read,授予User只读数据的权限
- readWrite,授予User读写数据的权限
-
数据库管理角色-库管理权限:dbAdmin、dbOwner、userAdmin;
- dbAdmin,在当前dB中执行管理操作
- dbOwner,在当前DB中执行任意操作
- userAdmin,在当前DB中管理User
-
集群管理角色-集群管理权限:clusterAdmin、clusterManager、clusterMonitor、hostManager;
- clusterAdmin,授予管理集群的最高权限
- clusterManager:授予管理和监控集群的权限
- clusterMonitor:授予监控集群的权限,对监控工具具有readonly的权限
- hostManager:管理Server
-
备份恢复角色-备份恢复权限:backup、restore;
-
所有数据库角色-全局权限:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、 dbAdminAnyDatabase
- readAnyDatabase:授予在所有数据库上读取数据的权限
- readWriteAnyDatabase:授予在所有数据库上读写数据的权限
- userAdminAnyDatabase:授予在所有数据库上管理User的权限
- dbAdminAnyDatabase:授予管理所有数据库的权限
-
超级用户角色-超级用户:root
4.3.3-权限配置常用命令
1、show users; #查看当前库下的用户
2、db.dropUser("username") #删除用户
3、db.updateUser( "admin",{pwd:"password"}); #修改用户密码
4、db.auth("admin","password"); #密码认证
4.3.4-配置步骤
第1步:先给admin数据库创建超级管理用户
> use admin
> db.createUser({ user:'admin', pwd:'123456', roles:[{role:'root',db:'admin'}] })
user:用户名
pwd:密码
roles:角色
- role,指定角色
- db,指定数据库
第2步修改 Mongodb 数据库配置文件
找到数据库安装目录中下的bin
目录下的mongod.cfg
配置文件,开启安全验证配置
security:
authorization: enabled
重启mongodb服务,进入终端命令行,执行命令
net stop mongodb
net start mongodb
用超级管理员账户连接数据库
mongo admin -u "admin" -p "123456"
若更改了端口号,则必须指定端口号连接
mongo --port 端口号 admin -u "admin" -p "123456"
第3步给 指定的数据库(如:myblog)创建一个用户,只能访问指定的数据库(如:myblog)不能访问其他数据库
切换到myblog数据库,创建该数据库的用户名和密码及权限
> use myblog
> db.createUser({ user:'myblog', pwd:'123456', roles:[{role:'readWrite',db:'myblog'}] })
退出,连接myblog数据库
> exit
> mongo --port 28888 myblog -u "myblog" -p "123456"
4.4.5-NodeJs中连接数据库
// 连接数据库
const mongoose = require('mongoose')
mongoose.connect('mongodb://myblog:123456@localhost:28888/myblog',{useNewUrlParser: true,useUnifiedTopology: true})
4.4-MongoDB 数据的导入和导出
在 Mongodb 中我们使用 mongodump 命令来备份 MongoDB 数据。该命令可以导出所有数据到指定目录中。mongodump 命令可以通过参数指定导出的数据量级转存的服务器。使用mongorestore 命令来恢复备份的数据。
导出:
mongodump -h dbhost -d dbname -o dbdirectory
导入:
mongorestore -h dbhost -d dbname path
第五章:工具扩展篇
Navicat Premium v12.1.25 中文最新破解版
链接:https://pan.baidu.com/s/1KUhhCd-iJ4ahFVlF8R_QUQ
提取码:w6we