Node.js第四篇:快速上手mongodb

第一章:认识数据库

1.1-为什么要使用数据库

  • 动态网站中的数据都是存储在数据库中的,我们要开发动态网站,必须得学会操作数据库。
  • 数据库软件可以对数据高效的管理

1.2-什么是数据库

数据库就是存储数据的仓库,可以将数据分门别类的存储。它是独立于语言之外的软件,在后端编程中可以通过相关的API操作数据库

常见的数据库软件有,oracle、mysql、mongodb等。

在本篇中,我们学习nodejs操作mongodb数据库。

第二章:数据库环境搭建

2.1-下载MongoDB

官网:https://www.mongodb.com/

下载地址: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 FilesMongoDBServer4.2in

其次打开配置环境变量的窗口:

选中【我的电脑】或【此电脑】→鼠标右键点击→【选择属性】→【选择高级系统变量】→【点击环境变量】→【系统变量-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 : 10maxlength : [10, '自定义异常提示信息']
  • minlength 字符串最大长度。 如:minlength: 6minlength: [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数据库用户角色

  1. 数据库用户角色-库使用权限:read、readWrite;

    • read,授予User只读数据的权限
    • readWrite,授予User读写数据的权限
  2. 数据库管理角色-库管理权限:dbAdmin、dbOwner、userAdmin;

    • dbAdmin,在当前dB中执行管理操作
    • dbOwner,在当前DB中执行任意操作
    • userAdmin,在当前DB中管理User
  3. 集群管理角色-集群管理权限:clusterAdmin、clusterManager、clusterMonitor、hostManager;

    • clusterAdmin,授予管理集群的最高权限
    • clusterManager:授予管理和监控集群的权限
    • clusterMonitor:授予监控集群的权限,对监控工具具有readonly的权限
    • hostManager:管理Server
  4. 备份恢复角色-备份恢复权限:backup、restore;

  5. 所有数据库角色-全局权限:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、 dbAdminAnyDatabase

    • readAnyDatabase:授予在所有数据库上读取数据的权限
    • readWriteAnyDatabase:授予在所有数据库上读写数据的权限
    • userAdminAnyDatabase:授予在所有数据库上管理User的权限
    • dbAdminAnyDatabase:授予管理所有数据库的权限
  6. 超级用户角色-超级用户: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

原文地址:https://www.cnblogs.com/lpl666/p/12872532.html