• MongoDB 数据库概述及环境搭建


    1 数据库概述及环境搭建

    1.1 为什么要使用数据库

    动态网站中的数据都是存储在数据库中的
    数据库可以用来持久存储客户端通过表单收集的用户信息
    数据库软件本身可以对数据进行高效的管理

    1.2 什么是数据库

    数据库即存储数据的仓库,可以将数据进行有序的分门别类的存储。它是独立于语言之外的软件,可以通过 API 去操作它。

    常见的数据库软件有:mysql、mongoDB、oracle

    1.3 MongoDB 数据库下载安装

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

    还要下载 MongoDB Compass 图形界面软件,下载地址:https://www.mongodb.com/download-center/compass

    在安装过程中,Custom 自定义安装可以选择安装路径,以后都选择默认安装就可以了。

    相关概念:

    一个网站有多个网站应用,所以一个数据库有多个 database(库)

    一个网站应用有多种类数据,比如用户信息、商品信息,所以之下有 collection(类)

    一类数据小有多条数据,所以之下有 document(条)

    一条数据下有多种属性,所以之下有 field(属性)

    1.4 MongoDB 可视化软件

    MongoDB 可视化操作软件,是使用图形界面操作数据库的一种方式。

    MongoDB Compass 可以在安装 MongoDB 的时候安装,也可以单独安装。

    1.5 数据库相关概念

    在一个数据库软件中可以包含多个数据仓库,在每个数据仓库中可以包含多个数据集合,每个数据集合中可以包含多条文档(具体的数据)。

    1.6 Mongoose 第三方包

    使用 Node.js 操作 MongoDB 数据库需要依赖 Node.js 第三方包 mongoose

    它下面的 connect 方法可以连接数据库。

    使用 npm install mongoose 命令下载

    创建项目 database ,并在命令行工具切换到 database 目录下,进行安装,输入:

    npm install mongoose

    1.7 启动 MongoDB 

    在命令行工具中运行 net start mongoDB ,即可启动MongoDB,否则MongoDB将无法链接。

    在命令行工具中,停止MongoDB,输入:

    net stop MongoDB

    启动MongoDB,输入:

    net start mongoDB

    1.8 数据库链接

    使用 mongoDB 提供的 connect 方法即可连接数据库

    基本语法:

    mongoose.connect('mongodb://localhost/playground')
      .then(() => console.log('数据库连接成功'))
      .catch(err => console.log('数据库连接失败',err));

    例子:

    新建 01.js 文件,先引入 mongoose:

    const mongoose = require('mongoose');
    
    mongoose.connect('mongodb://localhost/playground')
      .then(() => console.log('数据库连接成功'))
      .catch((err) => console.log(err,'数据库连接失败'))

    回到命令行工具,输入:

    node 01.js

    结果是:

    可以看到数据库连接成功,但是在之前有一些 mongoose 的提示,说是:当前的 current URL 解析器,已经被废弃掉了,在将来的版本中将会被删除掉,然后让你使用新的解析器。{ useNewUrlParser: true, useUnifiedTopology: true }

    修改下代码:

    // 引入mongoose 第三方模块,用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
      // 连接成功
      .then(() => console.log('数据库连接成功'))
      // 连接失败
      .catch((err) => console.log(err,'数据库连接失败'));

    在命令行工具中重新运行,结果:

    1.9 创建数据库

    在 MongoDB 中不需要显示创建数据库,如果正在使用的数据库不存在,MongoDB 会自动创建

    2 MongoDB 增删改查操作

    2.1 创建集合

    创建集合分为两步:一是对集合设置规则,二是使用规则创建集合。创建 mongoose.Schema 构造函数的实例即可创建集合。 

    语法:

    // 设定集合规则
    const courseSchema = new mongoose.Schema({
      name: String,
      author: String,
      isPublished: Boolean
    });
    // 创建集合并应用规则
    const Course = mongoose.model('Course', courseSchema); // courses

    mongoose.model 创建集合,第一个参数是集合的名称,集合名称的首字母应该大写,比如:Course,当实际上 mongoose 在数据库中创建的集合名称是:courses,是小写,后面加 s 代码复数,因为是集合。Course 接收的是 mongoose.model 的返回值:构造函数。

    例子:新建 02.js 文件:

    // 引入mongoose 第三方模块,用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
      // 连接成功
      .then(() => console.log('数据库连接成功'))
      // 连接失败
      .catch((err) => console.log(err,'数据库连接失败'));
    
    // 设定集合规则
    const courseSchema = new mongoose.Schema({
      name: String,
      author: String,
      isPublished: Boolean
    });
    // 使用规章创建集合
    const Course = mongoose.model('Course', courseSchema); // courses

    回到命令行工具,输入:

    node 02.js

    提示:数据库连接成功。

    然后打开 MongoDBCompass 软件,刷新后并没有看到我们写的 playground 数据库,是因为没有为集合插入数据,所以就没有创建数据库。下面我们需要插入一条数据。

    2.2 创建文档

    创建文档实际上就是向集合中插入数据

    分为两步:

    1)创建集合实例

    2)调用实例对象下的 save 方法,将数据保存到数据库中

    基础语法:

    // 创建集合实例
    const course = new Course({
      name: 'Node.js course',
      author: 'joe',
      tags: ['node', 'backend'],
      isPublished: true
    });
    // 将数据保存到数据库中
    course.save();

    继续编辑 02.js 文件:

    // 引入mongoose 第三方模块,用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
      // 连接成功
      .then(() => console.log('数据库连接成功'))
      // 连接失败
      .catch((err) => console.log(err,'数据库连接失败'));
    
    // 设定集合规则
    const courseSchema = new mongoose.Schema({
      name: String,
      author: String,
      isPublished: Boolean
    });
    // 使用规章创建集合
    const Course = mongoose.model('Course', courseSchema); // courses
    // 创建集合实例
    const course = new Course({
      name: 'Node.js 基础',
      author: 'joe',
      isPublished: true
    });
    // 将数据保存到数据库中
    course.save();

    回到命令行工具中,重新运行,输入:

    node 02.js

    然后打开  MongoDBCompass 软件,刷新后就可以看到 playground 数据库了

     

    点击 courses 集合,可以看到里面有一条数据。

     

    _id 属性段是当前数据的唯一标识,是数据库自动生成的。

    还有一种方式可以向集合中插入文档。

    语法:

    Course.create({name: 'Node.js 基础', author: 'joe', isPublished: true}, (err, doc) => {
      // 错误对象
      console.log(err)
      // 当前插入的文档
      console.log(doc)
    });

    例子:

    新建 03.js 文件:

    // 引入mongoose 第三方模块,用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
      // 连接成功
      .then(() => console.log('数据库连接成功'))
      // 连接失败
      .catch((err) => console.log(err,'数据库连接失败'));
    
    // 设定集合规则
    const courseSchema = new mongoose.Schema({
      name: String,
      author: String,
      isPublished: Boolean
    });
    // 使用规章创建集合
    // 第1个参数代表集合名称
    // 第2个参数代表集合规则
    const Course = mongoose.model('Course', courseSchema); // courses
    // 向集合中插入文档
    Course.create({name: 'JavaScript', author: 'joe', isPublished: false}, (err, result) => {
      // 错误对象
      console.log(err)
      // 当前插入的文档
      console.log(result)
    });

    回到命令行工具,输入:

    node 03.js

    结果:

     

    第1个参数 null 代表:插入是成功的;第2个参数是插入文档的那一条数据。

    回到 MongoDBCompass 软件,点击刷新,可以看到有2条数据了:

    关于数据库的所有操作,都是异步操作。

    mongoose 当中提供的 API 也支持 promise 的方式:

    Course.create({name: 'JavaScript 基础', author: 'joe', isPublished: true})
      .then(doc => console.log(doc))
      .catch(err => console.log(err))

    例子:修改下 03.js 文件:

    // 引入mongoose 第三方模块,用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true, useUnifiedTopology: true })
      // 连接成功
      .then(() => console.log('数据库连接成功'))
      // 连接失败
      .catch((err) => console.log(err,'数据库连接失败'));
    
    // 设定集合规则
    const courseSchema = new mongoose.Schema({
      name: String,
      author: String,
      isPublished: Boolean
    });
    // 使用规章创建集合
    // 第1个参数代表集合名称
    // 第2个参数代表集合规则
    const Course = mongoose.model('Course', courseSchema); // courses
    
    // 向集合中插入文档
    // Course.create({name: 'JavaScript', author: 'joe', isPublished: false}, (err, result) => {
    //   // 错误对象
    //   console.log(err)
    //   // 当前插入的文档
    //   console.log(result)
    // });
    
    Course.create({name: 'JavaScript123', author: 'joe', isPublished: false})
      .then(result => {
        console.log(result)
      })
      .catch(err => {
        console.log(err)
      })

    回到命令行工具中重新运行 03.js

    结果:

    回到 MongoDBCompass 软件,点击刷新,可以看到有3条数据了。

    总结:可以通过 create 方法来向集合中插入数据,它有两种接收异步 API 的方式:第一种通过回调函数的方式,第二种通过 promise 对象的方式。 

    2.3 mongoDB 数据库导入数据

    把现成的数据插入到数据库中,需要用 到mongoDB 提供的命令:mongoimport

    mongoimport -d 数据库名称 -c 集合名称 --file 要导入的数据文件

    在命令行工具中输入:mongoimport,提示无法识别,并没有找到 mongoimport 的可执行文件,我们需要手动将命令的所在的目录添加到系统环境变量 path 中去,命令行工具才能找到 mongoimport 命令的可执行文件。命令的所在目录就是mongoDB 数据库的安装目录。

    打开本地电脑的 mongoDB 安装目录,在里面找到 bin目录,打开可以看到 mongoimport.exe 文件,并复制它的目录:

    把复制好的目录添加到系统的环境变量 path 中:

     

    保存后,需要把命令行工具进行重启,记得重启好后,要切换到 database 目录下。

    然后将准备好的 user.json 文件中的数据,导入到数据库中。在命令行输入:

    mongoimport -d playground -c users --file ./user.json

    结果:表示找到了本机当做的数据库,导入了6个文档。

     

    然后打开 Compass 软件,点击刷新,可以看到新增加了一个 users 集合,里面有6条数据:

     

    2.4 查询文件

    语法:

    // 根据条件查找文档(条件为空则查找所有文档)
    Course.find().then(result => console.log(result))

    find() 返回的是:文档集合。

    例子:

    新建 04.js 文件:

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    // 创建集合规则
    const userSchema = new mongoose.Schema({
        name: String,
        age: Number,
        email: String,
        password: String,
        hobbies: [String]
    });
    
    // 使用规则创建集合
    const User = mongoose.model('User', userSchema);
    
    // 查询用户集合中的所有文档
    User.find().then(result => console.log(result));

    切换到命令行工具,输入:

    node 04.js

    可以看到结果:返回的是一个数组,数组里包含了多个对象。

     

    可以在 find() 方法里传递一个对象,那么这个对象就是查询条件。

    例如:查询用户 id 为多少的,在 Compass 里,随便复制一个 id 值,修改下 04.js 文件:

    // 使用规则创建集合
    const User = mongoose.model('User', userSchema);
    
    // 查询用户集合中的所有文档
    // User.find().then(result => console.log(result));
    // 通过_id字段查找文档
    User.find({_id: '5c09f1e5aeb04b22f8460965'}).then(result => console.log(result))

    在命令行工具中输入:node 04.js

    可以看到查询结果:

    可以看到返回的还是一个数组,里面有一条数据。

    总结:通过 find() 方法查询出的数据,无论有多少,它返回的都是一个数组。如果查找的数据不存在,那么会返回一个空数组。

    另外一个方法 findOne:

    语法:

    // 根据条件查找文档
    Course.findOne({name: 'node.js 基础'}).then(result => console.log(result))
    findOne方法返回一个对象。如果不加查询条件,那么返回的是当前集合中的第一条数据。

    例子:继续编辑04.js 文件:

    // 查询用户集合中的所有文档
    // User.find().then(result => console.log(result));
    // 通过_id字段查找文档
    // User.find({_id: '5c09f1e5aeb04b22f8460965'}).then(result => console.log(result))
    
    // findOne方法返回一条文档 默认返回当前集合中的第一条文档
    User.findOne().then(result => console.log(result))

    回到命令工具,输入:node 04.js

    结果:返回的是一个对象(第一条数据文档)

    例子:查询名字是“李四”的数据:

    User.findOne({name: '李四'}).then(result => console.log(result))

    匹配大于$gt  小于$lt:

    语法:

    // 匹配大于 小于
    User.find({age: {$gt: 20, $lt: 50}}).then(result => console.log(result))

    例子:04.js 文件:

    // 查询用户集合中年龄字段大于20并且小于40的文档
    User.find({age: {$gt: 20, $lt: 40}}).then(result => console.log(result))

    命令行工具中,输入:node 04.js

    结果:

    匹配包含 $in:

    语法:

    // 匹配包含
    User.find({hobbies: {$in: ['足球']}}).then(result => console.log(result))

    例子:

    // 查询用户集合中hobbies字段值包含足球的文档
    User.find({hobbies: {$in: ['足球']}}).then(result => console.log(result))

    结果是:

    选择要查询的字段 select:

    // 选择要查询的字段
    User.find().select('name email').then(result => console.log(result))

    例子:

    // 选择要查询的字段 名字和邮件地址
    User.find().select('name email').then(result => console.log(result))

    结果:

    可以看到 _id 是默认字段,自动查询出来的。如果不想查询出 _id 字段,写作:-_id

    例子:

    // 选择要查询的字段
    User.find().select('name email -_id').then(result => console.log(result))

    结果:

    对查询出来的数据进行排序 sort

    语法:

    // 将数据按照年龄进行排序
    User.find().sort('age').then(result => console.log(result))

    例子:根据年龄字段进行升序排列

    // 根据年龄字段进行升序排列
    User.find().sort('age').then(result => console.log(result))
    
    // 根据年龄字段进行降序排列
    User.find().sort('-age').then(result => console.log(result))

    跳过数据skip 和 限制查询数量limit

    语法:

    // skip 跳过多少条数据 limit 限制查询数量
    User.find().skip(2).limit(3).then(result => console.log(result))

    例子:

    // 查询文档跳过前两条结果 限制显示3条结果
    User.find().skip(2).limit(3).then(result => console.log(result))

    2.5 删除文档

    删除单个文档:

    // 删除单个
    Course.findOneAndDelete({}).then(result => console.log(result))

    如果查询条件包含了多条文档,那么会将第一个匹配的文档删除。返回值是删除的这条文档。

    例子:新建 05.js 文件:

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    // 创建集合规则
    const userSchema = new mongoose.Schema({
        name: String,
        age: Number,
        email: String,
        password: String,
        hobbies: [String]
    });
    
    // 使用规则创建集合
    const User = mongoose.model('User', userSchema);
    
    // 查找到一条文档并且删除
    // 返回删除的文档
    // 如何查询条件匹配了多个文档 那么将会删除第一个匹配的文档
    User.findOneAndDelete({_id: '5c09f267aeb04b22f8460968'}).then(result => console.log(result))

    在命令行工具,输入:

    node 05.js

    返回一条文档,也就是被删除的这条数据。

    然后打开 Compass 软件,刷新后可以看到只剩下5条数据了,‘王五’的那条数据被删除了。

    删除多个文档:

    // 删除多个
    User.deleteMany({}).then(result => console.log(result))

    依然返回 promise 对象。

    例子:05.js 文件:

    // 删除多条文档,如果查询条件为空对象,那么会把数据库中 User 集合中的所有文档都删除
    User.deleteMany({}).then(result => console.log(result))

    回到命令行工具,输入:node 05.js

    结果:

    然后打开 Compass 软件,刷新后可以看到 users 这个集合里是空的了。

    2.6 更新文档

    更新单个文档:

    // 更新单个文档
    User.updateOne({查询条件}, {要修改的值}).then(result => console.log(result))

    如果有多个查询结果,会更新第一条文档。

    例子:

    因为我们上面把users集合里的数据都删除了,下面要重新导入下 user.json 文件中的数据,在命令行工具中输入:

    mongoimport -d playground -c users --file ./user.json

    然后新建 06.js 文件:

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    // 创建集合规则
    const userSchema = new mongoose.Schema({
        name: String,
        age: Number,
        email: String,
        password: String,
        hobbies: [String]
    });
    
    // 使用规则创建集合
    const User = mongoose.model('User', userSchema);
    // 更新集合中的单个文档
    User.updateOne({name: '李四'}, {age: 120, name: '李狗蛋'}).then(result => console.log(result))

    在命令行工具输入:

    node 06.js

    结果:

    打开 Compass 软件,刷新后可以看到 users 这个集合中的“李四”,变为了“李狗蛋”,年龄改为了120。

    更新多个文档:

    // 更新多个文档
    User.updateMany({查询条件}, {要更改的值}).then(result => console.log(result))

    查询条件为空的话,表示更新所有文档。

    例子:修改 06.js 文件:

    // 更新集合中的单个文档
    // User.updateOne({name: '李四'}, {age: 120, name: '李狗蛋'}).then(result => console.log(result))
    
    // 更新集合中的多个文档
    User.updateMany({}, {age: 56}).then(result => console.log(result))

    在命令行工具中输入:

    node 06.js

    然后结果可以看到所有文档的年龄都改为了 56。

    2.6 mongoose 验证 

    在创建集合规则时,可以设置当前字段的验证规则,验证失败则输入插入失败。

    ● required.true 必传字段

    例子:新建 07.js 文件:

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    const postSchema = new mongoose.Schema({
      title: {
        type: String,
        required: true
      }
    });
    
    // 使用规则创建集合
    const Post = mongoose.model('Post', postSchema);
    
    Post.create({}).then(result => console.log(result))

    在命令行工具输入:node 07.js,会提示错误信息。

    因为设置 title 字段为必传字段,但是插入文档的时候为空对象,所以会提示错误。

    如果把 required: true 去掉,在重新运行 07.js,即使插入空对象,也会提示插入成功。然后打开 Compass 软件,会发现多了一个 posts 集合。

    如果想自定义报错信息的话,可以修改设置为:

    title: {
        type: String,
        required: [true, '请传入文章标题']
      }

    第一个参数 true 为必传,第二个参数就是自定义的错误信息。

    在命令行工具中重新输入:node 07.js

    结果的自定义错误信息:

    ● minlength 最小长度

    ● maxlength 最大长度

    title: {
        type: String,
        required: [true, '请传入文章标题'],
        minlength: 2,
        maxlength: 5
      }

    例子:

    const postSchema = new mongoose.Schema({
      title: {
        type: String,
        required: [true, '请传入文章标题'],
        minlength: 2,
        maxlength: 5
      }
    });
    
    // 使用规则创建集合
    const Post = mongoose.model('Post', postSchema);
    
    Post.create({title: 'a'}).then(result => console.log(result))

    运行后会提示:

    Post validation failed: title: Path `title` (`a`) is shorter than the minimum allowed length (2).

    在修改代码为 title: 'aaaaaa' 

    运行后会提示:

    Post validation failed: title: Path `title` (`aaaaaa`) is longer than the maximum allowed length (5).

    当然 minlength 和 maxlength 也可以自定义错误信息,格式同 required 一样:

    minlength: [2, '文章标题长度不能小于2'],
    maxlength: [5, '文章标题长度最大不能超过5']

    ● trim: true 去除字符串两端空格

    例子:

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    const postSchema = new mongoose.Schema({
      title: {
        type: String,
        required: [true, '请传入文章标题'],
        minlength: [2, '文章标题长度不能小于2'],
        maxlength: [5, '文章标题长度最大不能超过5'],
        trim: true
      }
    });
    
    // 使用规则创建集合
    const Post = mongoose.model('Post', postSchema);
    
    Post.create({title: '    aaa      '}).then(result => console.log(result))

    在命令行工具中输入: node 07.js

    结果:可以看到两端的空格没有了,标题就是:aaa

    ● min: 2 数值最小为2

    ● max: 100 数值最大为100

    例子: 修改 07.js 文件

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    const postSchema = new mongoose.Schema({
      title: {
        type: String,
        // 必选字段
        required: [true, '请传入文章标题'],
        // 字符串的最小长度
        minlength: [2, '文章标题长度不能小于2'],
        // 字符串的最大长度
        maxlength: [5, '文章标题长度最大不能超过5'],
        // 去除字符串两边的空格
        trim: true
      },
      age: {
        type: Number,
        min: 18,
        max: 100
      }
    });
    
    // 使用规则创建集合
    const Post = mongoose.model('Post', postSchema);
    
    Post.create({title: 'aa', age: 10}).then(result => console.log(result))

    运行后结果提示报错:

    Post validation failed: age: Path `age` (10) is less than minimum allowed value (18).

    当然如果想自定义错误信息,格式和上面是一样的。

    ● default 默认值

    例子:修改 07.js

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    const postSchema = new mongoose.Schema({
      title: {
        type: String,
        // 必选字段
        required: [true, '请传入文章标题'],
        // 字符串的最小长度
        minlength: [2, '文章标题长度不能小于2'],
        // 字符串的最大长度
        maxlength: [5, '文章标题长度最大不能超过5'],
        // 去除字符串两边的空格
        trim: true
      },
      age: {
        type: Number,
        min: 18,
        max: 100
      },
      publishDate: {
        type: Date,
        // 默认值
        default: Date.now
      }
    });
    
    // 使用规则创建集合
    const Post = mongoose.model('Post', postSchema);
    
    Post.create({title: 'aa', age: 60}).then(result => console.log(result))

    在命令行工具中输入:node 07.js

    结果:

    回到 Compass 软件,发现 posts 集合多了一条文档:

    ● enum: ["html", "css", "javascript", "node.js"]  枚举,列举出当前字段可以拥有的值(只能传固定的一些值)

    例子:修改 07.js

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    const postSchema = new mongoose.Schema({
      title: {
        type: String,
        // 必选字段
        required: [true, '请传入文章标题'],
        // 字符串的最小长度
        minlength: [2, '文章标题长度不能小于2'],
        // 字符串的最大长度
        maxlength: [5, '文章标题长度最大不能超过5'],
        // 去除字符串两边的空格
        trim: true
      },
      age: {
        type: Number,
        // 数字的最小范围
        min: 18,
        // 数字的最大范围
        max: 100
      },
      publishDate: {
        type: Date,
        // 默认值
        default: Date.now
      },
      category: {
        type: String,
        // 枚举 列举出当前字段可以拥有的值
        enum: ['html', 'css', 'javascript', 'node.js']
      }
    });
    
    // 使用规则创建集合
    const Post = mongoose.model('Post', postSchema);
    
    Post.create({title: 'aa', age: 60, category:'java'}).then(result => console.log(result))

    结果:提示报错信息

    Post validation failed: category: `java` is not a valid enum value for path `category`.

    把代码中的类型修改为:html

    Post.create({title: 'aa', age: 60, category:'html'}).then(result => console.log(result))

    就可以运行插入成功了。

    ● validate:自定义验证器,mongoose 提供了自定义验证规则

    例子:修改 07.js

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    const postSchema = new mongoose.Schema({
      title: {
        type: String,
        // 必选字段
        required: [true, '请传入文章标题'],
        // 字符串的最小长度
        minlength: [2, '文章标题长度不能小于2'],
        // 字符串的最大长度
        maxlength: [5, '文章标题长度最大不能超过5'],
        // 去除字符串两边的空格
        trim: true
      },
      age: {
        type: Number,
        // 数字的最小范围
        min: 18,
        // 数字的最大范围
        max: 100
      },
      publishDate: {
        type: Date,
        // 默认值
        default: Date.now
      },
      category: {
        type: String,
        // 枚举 列举出当前字段可以拥有的值
        enum: ['html', 'css', 'javascript', 'node.js']
      },
      author: {
        type: String,
        validate: {
          validator: v => {
            // 返回一个布尔值
            // true 表示验证成功;false 表示验证失败
            // v 表示要验证的值
            return v && v.length > 4
          },
          // 自定义错误信息
          message: '传入的值不符合验证规则'
        }
      }
    });
    
    // 使用规则创建集合
    const Post = mongoose.model('Post', postSchema);
    
    Post.create({title: 'aa', age: 60, category:'html', author: 'bd'}).then(result => console.log(result))

    运行后结果:

    Post validation failed: author: 传入的值不符合验证规则

    create 方法返回的是 promise 对象,可以通过 .then() 方法拿到插入成功的返回值,所以我们也可以通过 .catch() 方法拿到插入失败的失败对象。
    修改下 07.js 代码:
    Post.create({title: 'aa', age: 60, category:'html', author: 'bd'})
      .then(result => console.log(result))
      .catch(error => console.log(error))

    重新运行:node 07.js

    结果:author 字段插入的值不符合规章

    如果插入文档中有多个字段不符合规则:

    Post.create({title: 'aa', age: 60, category:'java', author: 'bd'})
      .then(result => console.log(result))
      .catch(error => console.log(error))

    运行后的结果:category 字段和 author 字段插入的值都不符合规章

     

    可以看到第一层是 errors,然后里面有 category 对象和 author 对象,再里面的 message 字段为错误信息。

    那么我们就可以把 .cacth 里面写一个遍历数组,把错误信息都输出出来:

    Post.create({title: 'aa', age: 60, category:'java', author: 'bd'})
      .then(result => console.log(result))
      .catch(error => {
        // 获取错误信息对象
        const err = error.errors
        // 循环错误信息对象
        for(var i in err) {
          console.log(err[i].message);
          // console.log(err[i]['message']);
        }
      })

    重新运行后可以看到结果:

    下面我们把第一个错误信息也自定义下:

    category: {
        type: String,
        // 枚举 列举出当前字段可以拥有的值
        enum: {
          values: ['html', 'css', 'javascript', 'node.js'],
          message: '分类名称要在一定的范围内才可以'
        }
      },

    重新运行后的结果:

    3.7 集合关联

    通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同的集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联。

    ● 使用 id 对集合进行关联

    ● 使用 populate 方法进行关联集合查询

    语法:

    // 用户集合
    const User = mongoose.model('User', new mongoose.Schema({ name: { type: String} }));
    // 文章集合
    const Post = mongoose.model('Post', new mongoose.Schema({
      title: { type: String },
      // 使用 id 将文章集合和用户集合进行关联
      author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
    }));
    
    // 联合查询
    Post.find()
      .populate('author')
      .then((err, result) => console.log(result));
    ObjectId  就是  _id

    例子:新建 08.js 文件:

    // 引入mongoose第三方模块 用来操作数据库
    const mongoose = require('mongoose');
    // 数据库连接
    mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true})
        // 连接成功
        .then(() => console.log('数据库连接成功'))
        // 连接失败
        .catch(err => console.log(err, '数据库连接失败'));
    
    // 用户集合规则
    const userSchema = new mongoose.Schema({
        name: {
            type: String,
            required: true
        }
    });
    // 文章集合规则
    const postSchema = new mongoose.Schema({
        title: {
            type: String
        },
        // 使用 id 将文章集合和用户集合进行关联
      author: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User' 
      }
    });
    // 用户集合
    const User = mongoose.model('User', userSchema);
    // 文章集合
    const Post = mongoose.model('Post', postSchema);
    
    // 创建用户
    User.create({name: 'joe'}).then(result => console.log(result));

    在命令行工具中,输入:

    node 08.js

    结果:创建用户成功

    回到 Compass 软件中,刷新可以看到:创建的用户 joe

    然后进行创建文章:

    // 创建用户
    // User.create({name: 'joe'}).then(result => console.log(result));
    // 创建文章 author 值为用户的 id
    Post.create({titile: '123', author: '5eb9057561a07b1680de2a21'}).then(result => console.log(result));

    运行后可以看到结果:

    回到 Compass 软件中,刷新可以看到:创建的文章

    然后进行查询:

    // 创建用户
    // User.create({name: 'joe'}).then(result => console.log(result));
    // 创建文章 author 值为用户的 id
    // Post.create({title: '123', author: '5eb9057561a07b1680de2a21'}).then(result => console.log(result));
    // 联合查询
    Post.find().populate('author').then(result => console.log(result))

    重新运行后结果:

    2.8 案例:用户信息增删改查 

    1、搭建网站服务器:实现客户端与服务端的通信
    2、连接数据库,创建用户集合,向集合中插入文档
    3、当用户访问 /list 时,将所有用户信息查询出来
    4、将用户信息和表格 HTML 进行拼接,并将拼接结果响应回客户端
    5、当用户访问 /add 时,呈现表单页面,并实现添加用户信息功能
    6、当用户访问 /modify 时,呈现修改页面,并实现修改用户信息功能
    7、当 用户访问 /delete 时,实现删除用户功能

    具体代码:

    https://www.cnblogs.com/joe235/p/12869891.html 

  • 相关阅读:
    How to deploy the ASP.NET MVC 3 website into the IIS7 on Windows server 2008
    NHibernate Notes3_How to set a default value of column
    NHibernate Notes2_Handling versioning and concurrency
    block定义与使用
    记住
    监听键盘高度
    超出父视图区域的点击相应
    监听键盘高度变化
    iOS开发上线升级流程
    NSTimer理解
  • 原文地址:https://www.cnblogs.com/joe235/p/12803421.html
Copyright © 2020-2023  润新知