• 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

  • 相关阅读:
    银行类题目
    Java基础-继承-编写一个Java应用程序,设计一个汽车类Vehicle,包含的属性有车轮个数 wheels和车重weight。小车类Car是Vehicle的子类,其中包含的属性有载人数 loader。卡车类Truck是Car类的子类,其中包含的属性有载重量payload。每个 类都有构造方法和输出相关数据的方法。最后,写一个测试类来测试这些类的功 能。
    Java-set集合
    Java——List集合
    java异常处理:建立exception包,建立Bank类,类中有变量double balance表示存款,Bank类的构造方法能增加存款,Bank类中有取款的发方法withDrawal(double dAmount),当取款的数额大于存款时,抛出InsufficientFundsException,取款数额为负数,抛出NagativeFundsException,如new Bank(100),
    java基础-继承:矩形体积类问题
    类的继承和多态性-编写Java应用程序,定义Animal类,此类中有动物的属性:名称 name,腿的数量legs,统计动物的数量 count;方法:设置动物腿数量的方法 void setLegs(),获得腿数量的方法 getLegs(),设置动物名称的方法 setKind(),获得动物名称的方法 getKind(),获得动物数量的方法 getCount()。定义Fish类,是Animal类的子类,
    实验三 类的继承和多态性
    java基础—继承题目:编写一个Animal类,具有属性:种类;具有功能:吃、睡。定义其子类Fish
    java基础,继承类题目:编写一个Java应用程序,该程序包括3个类:Monkey类、People类和主类 E
  • 原文地址:https://www.cnblogs.com/lpl666/p/12872532.html
Copyright © 2020-2023  润新知