• 04_数据库


    1 Web架构

    web总共分为三个部分:

    • 客户端
    • 服务器
    • 数据库

    web网站访问过程:

    • 客户端向服务器发送请求
    • 服务器操作数据库
    • 数据库将结果返回给服务器
    • 服务器将结果响应给客户端

    2 数据库概念

    数据库(Database)

    • 数据库是按照数据结构来组织、存储和管理数据的仓库
    • 程序在内存中运行,一旦程序运行结束或者计算机断电,程序运行中的数据都会丢失
    • 因此我们需要将一些程序运行的数据保存到硬盘当中,而数据库就是数据持久化的最佳选择
    • 简而言之,数据库就是存储数据的仓库

    数据库分类

    数据库主要分为两种:

    • 关系型数据库(RDBMS)
      • MySQL、Oracle、DB2、SQL Server
      • 关系数据库中都是数据表
    • 非关系型数据库(NoSQL - Not Only SQL)
      • SQL结构化查询语言
        • 所有关系型数据库都是使用SQL操作
        • 标准化语言,是一门语言
        • 比如W3C规范,是一种标准,由各个厂商实现
        • 每个厂商实现方式不完全一样
        • 标准化虽然可以带来开发和学习成本的简化,但是同时限制了创新的机会
      • MongoDB、Redis
      • 文档数据库MongoDB
      • 键值对数据库

    3 MongoDB 简介

    • MongoDB是为快速开发互联网Web应用设计的数据库系统
    • MongoDB设计目标是极简、灵活、作为Web应用栈的一部分
    • MongoDB的数据模型是面向文档的,文档是一种类似于JSON的结构
    • 简单来说就是MongoDB数据库存储的是各种各样的JSON
    • 增强版的JSON,叫做BSON,可以存储二进制数据,可以认为就是JSON

    4 安装MongoDB

    下载安装

    下载地址:https://www.mongodb.com/try/download/community

    • 偶数版为稳定版,奇数版为开发版
    • 对32位系统支持不好,不建议使用32位系统安装
    • 从官网下载MongoDB数据库安装包至本地,双击该安装包,根据安装提示一步一步操作,完成数据库的安装。

    配置环境变量

    • 我的电脑 -> 右键属性 -> 高级系统设置 -> 环境变量 -> 系统环境变量 -> 找到 Path
    • 双击Path -> 在弹窗内添加mongodb安装目录D:\Project\MongoDB\Server\5.0\bin-> 点击所有确定保存
    • win + R 键打开控制台 -> 输入 mongod -> 没有出现不是内部或外部命令说明可以使用了

    5 开启MongoDB服务

    • 在命令行工具中运行命令mongo,连接 mongodb,出现 > 说明启动成功
    • 默认监听 27017 端口
    • 默认端口不要修改,需要修改的话,最大不能超过 65535

    数据库(database)

    • 数据库服务器
      • 服务器用来保存数据
      • 最新版本默认已启动
    • 数据库客户端
      • 客户端用来操作服务器,对数据进行增删改查的操作

    6 基本概念

    数据库服务器里面可以有多个数据库。

    • 数据库(database)
      • 数据库是一个仓库,在仓库中可以存放多个集合
    • 集合(collection)
      • 集合类似于数组,在集合中可以存放多个文档
    • 文档(document)
      • 数据库中的最小单位,存储和操作的内容都是文档
    • 字段
      • 文档中的一条数据,属性名就是字段名
    • 数据库和集合都不需要手动创建
      • 当我们创建文档时,如果文档所在的集合或数据库不存在会自动创建

    7 安装可视化工具

    下载地址:https://www.mongodbmanager.com/download-mongodb-manager-free

    8 基本操作

    常用命令

    • 显示数据库
      • show dbsshow databases
    • 进入数据库
      • use test
    • 操作数据库
      • db 代表当前数据库
    • 显示数据集合
      • show collections

    CRUD (增删改查) 操作

    • 数据库中插入一个或多个文档
      • db.<集合名>.insert(doc)
      • db.<集合名>.insertOne(doc) 插入一个文档
      • db.<集合名>.insertMany(doc) 插入多个文档
      • 下面两个方法更像是第一个方法的拆分,但是下面两个语义更加清晰
      • 插入文档时,如果没有给文档指定 _id 属性,则数据库会自动为文档添加 _id,可以自己指定 _id
      • 该属性为文档的唯一标识,不可重复,根据时间戳+机器码生成 ObjectId(),确保数据唯一
    // 向 test 数据库中 person 集合插入一个新数据 {name:"张三",age:"18"}
    db.person.insert({name:"张三", age:"18"});
    // 多条数据
    db.person.insert([
        {name:"张三", age:"18"},
        {name:"李四", age:"18"},
        {name:"赵五", age:"18"}
    ]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 查询集合中所有符合条件的文档
      • db.<集合名>.find({}) 可以接受一个对象作为条件参数
      • {属性名1:值,属性名2:值} 查询属性是指定值的文档
      • db.<集合名>.findOne({}) 用来查询集合中符合条件的第一个文档
      • db.<集合名>.find({}).count() 查询所有结果的数量
    • 修改集合中符合条件的文档
      • db.<集合名>.update({查询条件},{新对象},{配置}) 默认只修改一个
      • db.<集合名>.updateOne({查询条件},{新对象}) 修改一个符合条件的文档
      • db.<集合名>.updateMany({查询条件},{新对象}) 同时修改多个符合条件的文档
      • db.<集合名>.replaceOne({查询条件},{新对象}) 替换一个符合条件的文档
      • 默认使用新对象替换旧对象
      • 如果需要修改指定的属性,而不是替换,需要使用“修改操作符”来完成修改
      • $set 可以修改文档中的指定属性
      • $unset 可以用来删除文档的指定属性
    db.person.update({name:"张三"},{
        $set: {
            sex: "男",
            address: "幸福村"
        }
    });
    
    // 修改多个
    db.person.update(
        {name:"张三"},
        {$set: {
            sex: "男",
            address: "幸福村"
        }},
        {multi: true}
    );
    
    db.person.update({name:"张三"},{
        $unset: {
            address: "111"
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 删除集合中符合条件的文档
      • db.<集合名>.remove({条件})
        • 删除符合条件的所有文档,第二个参数为 true 只删除一个
        • 条件必须设置,如果没有直接删除所有文档
      • db.<集合名>.deleteOne({条件}) 删除符合条件的一个文档
      • db.<集合名>.deleteMany({条件}) 删除符合条件的多个文档
      • db.<集合名>.drop() 删除集合
      • db.dropDatabase() 删除数据库
    • 数据库中数据一般不会真正的删除,所以删除的方法很少调用
      • 一般都是单独添加一个字段,表示数据是否删除
      • 这种删除只是程序上的删除,不是物理删除
      • 不建议使用物理删除,因为删除之后无法找回
    • 文档的属性值可以是一个文档,当一个文档的属性值是一个文档时,我们称这个文档叫做内嵌文档

    其他方法

    • skip((页码-1)*每页显示条数).limit(显示条数)
    • limit() 用于设置显示数据的上限
    • skip() 用于跳过指定数量的数据
    • sort() 需要传递一个对象指定排序规则,1 为升序,-1 为降序
      • db.user.find({}).sort({_id:1,name:-1})
      • db.user.find({},{name:1,_id:0})
    • $gt 大于
    • $gte 大于等于
    • $lt 小于
    • $lte 小于等于

    9 练习作业

    • 进入 user_manage 数据库
    • 向数据库中的 users 集合中插入文档
    • 文档的内容包含用户名、密码、年龄、爱好、邮箱、是否删除

    10 文档关系

    • 一对一(one to one)
      • 夫妻(一个丈夫对应一个妻子)
      • 可以使用内嵌文档的方式体现
    • 一对多(one to many)/ 多对一(many to one)
      • 用户 - 银行卡
      • 用户 - 订单
      • 可以通过内嵌文档的方式体现
      • 通过单个字段实现关联
    • 多对多(many to many)
      • 分类 - 商品
      • 老师 - 学生
      • 添加字段值为数组

    11 插件操作数据库

    • 大部分使用程序来完成数据库操作
    • Mongoose 让我们可以通过 Node 操作 MongoDB 模板
    • Mongoose 是对象文档模型(ODM)库,对原生的模块进行了封装,提供了更多的功能

    Mongoose 优势

    官方地址:http://www.mongoosejs.net/

    • 可以为文档创建一个模式结构(Schema)
    • 可以对模型中的对象/文档进行验证
    • 数据可以通过类型转换转换为对象
    • 可以使用中间件来应用业务逻辑挂钩
    • 比 Node 原生的 MongoDB 驱动更容易

    使用 Mongoose

    • 使用 npm install mongoose命令下载
    • 使用 const mongoose = require('mongoose'); 引入 mongoose
    • 使用 mongoose.connect('mongodb://localhost/user_manage');
      • 如果使用默认端口号(27017),可以省略不写
    • 监听 MongoDB 数据库的连接状态
      • mongoose 对象中有一个 connection 属性,表示数据库连接
      • 通过监视该对象,可以来监听数据库的连接与断开
      • mongoose.connection.once('open',function(){}) 数据库连接成功事件
      • mongoose.connection.once('close',function(){}) 数据库连接断开事件
    • 使用 mongoose.disconnect() 断开数据库连接(一般不使用)
      • 一般只需要连接一次,连接一次以后,除非停止服务器,否则连接不会断开

    Mongoose 对象

    • Schema(模式对象)
      • 定义约束了数据库中的文档结构
    • Model
      • Model 对象作为集合中的所有文档表示
      • 相当于 MongoDB数据库中的集合collection
    • Document
      • 表示集合中的具体文档

    Schema 对象

    const Schema = mongoose.Schema;
    // 创建 Schema(模式)对象
    let stuSchema = new Schema({
        name: String,
        age: Number,
        sex: {
            type: String,
            default: '男'
        },
        address: String
    });
    // 通过 Schema 来创建 Model
    // Model 代表的是数据库中的集合,通过 Model 才能对数据库进行操作
    // mongoose.model(modelName, Schema);
    // modelName 是要映射的集合名
    // mongoose 会自动将集合名变成复数
    let StuModel = mongoose.model('student', stuSchema);
    
    // 向数据库中插入一个文档
    // StuModel.create(doc, function(err){});
    StuModel.create({
        name: '孙悟空',
        age: 18,
        sex: '男',
        address: '花果山'
    }, function(err){
        if(!err){
            console.log('插入成功');
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    Model 方法

    • Model.create(doc(s), [callback]) 创建一个或多个文档并添加到数据库中
      • doc(s) 可以是一个文档对象,也可以是一个对象数组
      • callback 操作完成以后调用的回调函数
    StuModel.create({
        name: '孙悟空',
        age: 18,
        sex: '男',
        address: '花果山'
    }, function(err){
        if(!err){
            console.log('插入成功');
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • Model.find(conditions, [projection], [options], [callback]) 查询所有符合条件的文档
    • Model.findById(id, [projection], [options], [callback]) 根据文档id属性查询文档
    • Model.findOne([conditions], [projection], [options], [callback]) 查询符合条件的第一个文档
      • conditions 查询条件
      • projection 投影 需要获取的字段
        • 两种方式
        • {name: 1, _id: 0}
        • "name age -_id"
      • options 查询选项(skip limit
      • callback 回调函数。查询结果结果会通过回调函数返回,参数必选,不传没有返回值
        • 通过 find() 查询的结果,返回的对象就是 Document,文档对象
        • Document 对象是 Model 的实例
        • doc instanceof StuModel
    StuModel.find({ name: '孙悟空' }, { name: 1, _id: 0 }, { skip: 2, limint: 10 }, function (err, docs) {
        if (!err) {
            console.log(docs);
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • Model.update(conditions, doc, [options], [callback])
    • Model.updateMany(conditions, doc, [options], [callback])
    • Model.updateOne(conditions, doc, [options], [callback])
      • 修改一个或多个文档
      • conditions 查询条件
      • doc 修改后的对象
      • options 配置参数
      • callback 回调函数
    • Model.replaceOne(conditions, doc, [options], [callback])
    StuModel.updateOne({ name: '张三' }, { $set: { age: 20 } }, function (err) {
        if (!err) {
            console.log('修改成功');
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • Model.remove(conditions, [callback])
    • Model.deleteOne(conditions, [callback])
    • Model.deleteMany(conditions, [callback])
      • 删除一个或多个文档
      • conditions 查询条件
      • callback 回调函数
    StuModel.remove({ name: '张三' }, function (err) {
        if (!err) {
            console.log('删除成功');
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • Model.count(conditions, [callback])
      • 统计文档的数量
    Model.count({ name: '张三' }, function (err, count) {
        if (!err) {
            console.log(count);
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Document 对象

    • Document 和集合中的文档一一对应,Document 是 Model 的实例
    • 通过 Model 查询到的结果都是 Document
    • Model#save([options], [fn]) 保存文档对象
    // 创建一个Document
    let stu = new StuModel({
        name: '孙悟空',
        age: 18,
        sex: '男',
        address: '花果山'
    });
    
    // Document 方法
    stu.save(function(err){
        if(!err){
            console.log('插入成功');
        }
    });
    
    StuModel.findOne({}, function (err, doc) {
        if (!err) {
            console.log(doc);
            // 修改方式1
            doc.update({$set:{age:20}},function(err){
                if(!err){
                    console.log('修改成功');
                }
            })
            // 修改方式2
            doc.age = 20;
            doc.save();
            // 删除
            doc.remove(function(err){
                if(!err){
                    console.log('删除成功');
                }
            });
            // 获取属性值
            console.log(doc.get('age'));
            console.log(doc.age);
            // 设置属性值
            doc.set('name', '张小三');
            doc.name = '张小三';
            // 获取 _id 值
            doc._id
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    模块化连接

    • 定义一个模块连接数据库
    // tools/conn_mongo.js
    const mongoose = require('mongoose');
    mongoose.connect('mongodb://localhost/user_manage');
    mongoose.connection.once('open', function () {
        console.log('数据库连接成功');
    })
    
    // index.js
    require('./tools/conn_mongo');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 定义一个模块,操作 Student 模型
    // models/student.js
    const mongoose = require('mongoose');
    const Schema = mongoose.Schema;
    const stuSchema = new Schema({
        name: String,
        age: Number,
        sex: {
            type: String,
            default: '男'
        },
        address: String
    });
    // 定义模型
    const StuModel = mongoose.model('student', stuSchema);
    module.exports = StuModel;
    
    // index.js
    let stu = require('./models/student');
    stu.find({}, function(err, docs){
        if(!err){
            console.log(docs);
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    OpenCV C++ 图像 批处理 (批量调整尺寸、批量重命名)
    springboot服务端接口公网远程调试 - 实现HTTP服务监听【端口映射】
    ctfshow学习记录-misc入门(图片篇-颜色通道50-59)
    java119-set类
    LeetCode刷题系列 -- 32. 最长有效括号
    java-php-python-景区失物招领平台演示录像计算机毕业设计
    关于Input【type=number】可以输入e问题及解决方案
    UE5.1_自定义配置文件读取
    串流直播流媒体视频发布平台功能模块和产品技术参数
    【C++】侯捷:C++面向对象-笔记-02
  • 原文地址:https://blog.csdn.net/zhangchen124/article/details/133647039