【Node.js】初识MongoDB数据库

数据库

一、基本概念

  • 数据库即存储数据的仓库,可以将数据进行有序的分门别类的存储

    它是独立于语言之外的软件,可以通过API去操作它。

  • 一个数据库软件中可以包含多个数据仓库

  • 每个数据仓库中可以包含多个数据集合

  • 每个数据集合中可以包含多条文档(具体的数据)

    术语解释说明
    database数据库, 数据库软件中可以建立多个数据库
    collection集合,一组数据的集合
    document文档,一条具体的数据
    filed字段,文档中的属性名称

二、MongoDB数据库

01. 需要下载

  • MongoDB

    数据库

  • MongoDB Compass

    可视化数据库管理软件

  • Mongoose

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

    使用 npm install mongoose命令下载


02. 启动MongoDB

  • 使用命令行

    net start mongoDB
    
    net stop mongoDB
    

03. 数据库连接

数据库的所有操作都是异步的

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

    mongoose.connect("mongodb://localhost/database")
    .then( () => {
        console.log("数据库连接成功");
    })
    .catch( (err) => {
        console.1og("数据库连接失败",err);
    })
    
    • mongoose.connect()返回一个 Promise 对象

      mongodb://localhost/database

      mongodb://localhost:数据库地址

      database:数据库名称

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

04. 创建集合

  • 步骤

    1. 对集合设定规则
    2. 创建集合

    创建 mongoose.Schema 构造函数的实例即可创建集合

  • 语法

    // 创建集合规则
    const studentSchema = new mongoose.Schema({
        // 这里是集合规则,包含属性和属性类型
        name: String,
        age: Number, 
        isGraduation: Boolean
    });
    // 使用规则 创建集合
    const Student = mongoose.model("Student", studentSchema);
    
    • 创建集合规则:mongoose.Schema("属性对象")

      • 这是一个构造函数,创建集合即创建这个构造函数的实例对象
      • 传递一个对象进去,对象中的属性,即为这个集合的文档的属性
    • 创建集合:mongoose.model("集合名称",集合规则)

      • 集合名称首字母要大写,且创建后在数据库的名称实际为复数形式(小写的)

        即集合名称为 Student

        数据库名称为 students

      • 它的返回值是这个集合的构造函数


05. 创建文档

实际上就是向集合中插入数据


数据库中有数据才会显示数据库

  • 步骤

    1. 创建集合实例
    2. 调用实例对象下的save方法将数据保存到数据库中
  • 语法

    // 创建集合实例
    const student = new Student({
        name: "Ruo van",
        age: 24,
        isGraduation: true
    });
    
    // 将数据保存到数据库中:调用实例的save()方法
    student.save();
    
    • 文档会自动生成一个唯一标识的_id属性

  • 另一种方法

    集合.create({属性对象},callback);


    向集合中插入文档(数据)

    Student.create({
        name:"COmposition",
        age:18,
        isGraduation:true
    }, (err,doc) => {
        console.log(err);
      
        console.log(doc);
    });
    
    // .create() 返回一个 Promise 对象
    Student.create({}).then().catch();
    

  • 直接导入文档数据

    需要添加系统环境变量

    mongoimport -d 数据库名称 -C 集合名称 --file 要导入的数据文件
    
    • -d:被导入数据的数据库(database
    • -c:被导入数据的集合(collection
    • --file:要导入的数据文件

06. 查询文档

(1)根据条件查找文档

  • .find()

    集合.find().then();
    

    集合.find()返回一个 Promise 对象

    可以通过.then()获取结果


    结果是数组形式,数组包含多个对象,每个对象就是一条数据

    • 返回值始终是一个数组
    • 条件为空,则查询所有文档
    Student.find().then( (result) => {
        console.log(result);
    });
    
  • .findOne()

    集合.findOne().then();
    

    返回数据是一条对象形式的数据

    • 返回一条数据,默认返回第一条数据

  • 查询条件:

    • 等于指定值

      .find( {name: "username"} );
      

      查询集合中 name 字段属性值为 username 的数据

    • 大于、小于指定值:$gt$lt

      .find( { age: {$gt:20,$lt:30} } );
      

      查询集合中 age 字段属性值 大于20小于20 的数据

    • 包含指定值:$in

      .find( {hobbies: { $in: ["足球"] }} );
      

      查询集合中 hobbies字段属性中包含 足球 的数据

  • 查询字段

    • 选择指定字段:select()

      .find().select("name email -_id");
      

      在集合中指定字段 name email 中进行查询

      默认会查询_id字段

      在字段前添加短横线 - 可以不查询该字段

  • 排序

    • 对指定字段进行排序:sort()

      .find().sort("age");
      

      对集合 根据指定字段 age 进行从小到大的排序

      在字段前添加短横线 - 可以反向排序

  • 跳过数据

    • 跳过指定数量的数据:skip()

      .find().skip(2);
      

      跳过前两条数据 进行查询


      主要用于分页显示数据中

  • 限制数量

    • 限制数据查询 的数量:limit()

      .find().limit(2)
      

      限制查询到的数据的数量 显示为 2条数据


      主要用于分页显示数据中


07. 删除文档

  • 删除单个文档

    .findOneAndDelete();
    

    查询指定数据并删除它

    如果有多个,值删除第一条数据


    返回Promise对象,返回的是被删除的那一条数据

    可以通过.then()获得这个数据

  • 删除多个文档

    .deleteMany({查询条件});
    

    删除匹配条件的多个数据

    如果条件为空,则会删除所有数据


    返回值是一个对象:{n:2, ok:1}

    n ——代表删除的数据数量

    ok——代表删除操作成功


08. 更新文档

  • 更新一个文档

    .updateOne( {查询条件},{要修改的值} );
    
    .updateOne( {age: 123},{age: 345} );
    

    如果匹配多个文档,也只会更新第一条文档数据


    返回一个Promise对象,用.then()方法返回

    返回值是一个对象:

    n代表查询到的数据数量

    nModified代表被更新的数据

    ok属性为1,代表操作成功

  • 更新多个文档

    .updateMany( {查询条件},{要更改的值} );
    
    .updateMany( {},{age: 000} );
    

    查询条件为空,则更改所有数据


    返回值同updateOne()


09. mongoose验证

创建集合规则时,可以设置当前字段的验证规则

验证失败则输入插入失败

// 创建集合规则(加入验证)
const studentSchema = new mongoose.Schema({
    // 这里是集合规则,包含属性和属性类型
    name: {
        type: String,
        required: true// 设置为必须字段
        minlength: 2,	// 限制字符串最小长度
        maxlength: 13,	// 限制字符串最大长度
        trim:true		// 去除字符串两端空格
        unique:true		// 保证字段值唯一
    },
    age: {
        type: Number,
        min: 18,		// 限制最小数值
        max: 100		// 限制最大数值
    }, 
    birthday: {
        type: Date,
        default: Date.now()	// 设置默认值
    },
    sex: {
      	type: String,
      	enum: ["male","female"]	// 设置限制词
    },
    isGraduation: {
    	type: String,
        validate: {					//自定义验证规则
            validator: (v) => {
                return v > 60;
            },
            message: "传入的值不对"	// 自定义错误信息
        }
    }
});
  • 通过required对字段属性进行限制验证

    • 传入布尔值true,表示该字段为必须字段

    • 传入数组,可自定义报错信息

      required:[true,"该字段为必须字段"]
      

      第一个参数为布尔值

      第二个参数表示自定义报错信息

  • 通过minlengthmaxlength对字段属性长度进行限制验证

    • 传入数字,以限制长度

    • 传入数组,以自定义报错信息

      minlength: [2, "最小长度为2"]
      

      第一个参数为长度值

      第二个参数为自定义报错信息

  • 通过 minmax 对字段属性数值大小进行限制验证

  • 通过 default 设置字段属性的默认值

  • 通过 enum 枚举可能传入的值

    enum: ["male","female"]
    

    只能设置该字段属性值为enum中的值

    如果不是enum中的值,则验证失败

  • 通过validate自定义验证器

    validate: {
        validator: (v) => {
            return v > 60; 
        },
        message: "传入的值不符合验证规则"
    }
    

    validator中的函数返回一个布尔值,

    true代表验证成功

    false代表验证失败

    v代表要验证的值


    message用来自定义错误信息


10. 获取错误信息

  • Promise对象里的错误信息包含在errors对象里message属性里面

  • 语法

    .catch( (error) => {
        // 获取错误信息对象
        const err = error.errors;
        // 遍历对象
        for(let k in err){
            // 打印错误信息
            console.log( err[k].message );
        }
    });
    

11. 集合关联

通常不同集合的数据之间是有关系的

  • 使用id对集合进行关联

  • 使用populate()方法查询

    // 两个集合:学生,分数
    // 创建学生集合:规则+集合
    const studengtSchema = new mongoose.Schema({
        name: {
            type: String,
            required: true
        }    // 添加用户字段
        score: {
            // 类型是固定的,以关联
            type: mongoose.Schema.Types.ObjectId,
            // 用ref关联Score集合
            ref: "Score"
        }
    });
    const Student = mongoose.model("Student",studengtSchema);
    // 创建分数集合:规则+集合
    const scoreSchema = new mongoose.Schema({
        English: {
            type: Number
        },
        Chinese: {
            type: Number
        }
    })
    const Score = mongoose.model("Score",scoreSchema);
    
    // 使用populate查询,查询条件为字段
    Student.find().populate("score").then( (result)=>{
        console.log(result)
    });
    

三、模板引擎

模板引擎是第三方模块,可以让开发者以更加友好的方式拼接字符串,使项目代码更加清晰、更加易于维护

01. art-template模板引擎

  • 下载与使用

    npm install art-template
    
    const template = require("art-template");
    
    const str = template("模板路径", 数据);
    
  • 语法示例:

    <!-- 模板:index.art -->
    <div>
        <span>{{ data.name }}</span>
        <span>{{ data.age }}</span>
    </div>
    
    • 模板路径一般为:./views
    • 模板文件后缀是 .art ,内容是html格式
    const html = template("./views/index.art", {
        data: {
            name: "Ruovan",
            age: 24
        }
    });
    
    • template()方法用来拼接字符串

      • 第一个参数是模板路径(绝对路径)

        绝对路径需要引入 path 模块

      • 第二个参数是要在模板中展示的数据

      • 返回值是:拼接好的字符串

    • data:在模板中展示的数据

02.模板语法

  • art- template同时支持两种模板语法

    • 标准语法:{{ 数据 }}
    • 原始语法:<%= 数据 %>

    标准语法可以让模板更容易读写,原始语法具有强大的逻辑处理能力

  • 模板引擎默认不会解析html标签,要解析html标签,需要

    • 标准语法:{{@ 数据 }}
    • 原始语法:<%- 数据 %>
  • 条件判断

    • 标准语法

      {{if 条件}}
      ...
      {{else if 条件}}
      ...
      {{/if}}
      
    • 原始语法

      <% if(value) { %> ... <% } %>
      <% if(value) { %> ... <% } else if(value) { %> ... <% } %>
      
      <% if(条件) { %>
          ...
      <% }else if (条件) { %>
          ...
      <% > else { %>
          ...
      <% } %>
      
  • 循环语法

    • 标准语法

      {{each data}}
      	{{$value}}
      {{/each}}
      
    • 标准语法

      <% for(var i=0; i < data.length; i++) { %>
      	<%= target[i] %>
      <% } %>
      
  • 子模板

    使用子模板可以将网站公共区块(头部、底部)抽离到单独的文件中

    • 标准语法

      {{ include "./header.art" }}
      

      /header.art是一个单独的模块

    • 原始语法

      <% include("./header.art") %>
      
  • 模板继承

    使用模板继承可以将网站HTML骨架抽离到单独的文件中

    其他页面模板可以继承骨架文件


    不同的页面的元素内容、元素样式不一致

    因此需要预留位置以填充内容

    使用{{block "位置名称"}}...{{/block}}来预留位置


    通过{{extend "模板"}}来继承模板

    • 语法示例

      <body>
          {{block "content"}} {{/block}}
      </body>
      
      • body中预留这个位置 content
      <!-- 继承模板 -->
      {{extend "./common/layout.art"}}
      <!-- 填充模板 -->
      {{block "content"}}
      	<p>{{ data.name }}</p>	 
      {{/block}}
      
  • 模板配置

    • 向模板中导入变量 template.defaults.imports.变量名 = 变量值;
    • 设置模板根目录 template.defaults.root=模板目录
    • 设置模板默认后缀 template.defaults.extname=".art"

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值