nodejs——mongoose

了解数据库

  1. 关系型数据库是一种基于关系模型的数据库。
    • 数据以表格的形式存储,表格中的每一行是一个记录,每一列是一个字段,每个字段都有一个数据类型。关系型数据库使用结构化查询语言(SQL)来查询和管理数据。
    • 优点:数据结构清晰、数据关系明确数据一致性好
    • 缺点:可拓展性受限。不适合处理海量数据和非结构化数据。
  2. ==非关系型数据库(NoSQL)==是一种非结构化的数据库。
    • 数据以键值对、文档、图形等形式存储。非关系型数据库不需要预定义的模式,可以随时添加新的字段和数据类型。非关系型数据库通常使用非结构化查询语言来查询和管理数据。
    • 优点:可拓展性高、适合处理非结构化数据和海量数据、支持分布式部署
    • 缺点: 数据结构不够清晰、数据关系不够明确、数据一致性稍差。

总的来说,关系型数据库适合处理结构化数据,如订单、账户等;非关系型数据库适合处理大数据、非结构化数据和实时数据,如用户日志,社交媒体数据等。初学者可以根据自己的需求选择合适的数据库。

mongoose的使用

引入mongoose并连接mongodb
const mongoose = require('mongoose');
// 连接指定数据库(如果不存在就需要先创建数据库)
mongoose
  .connect('mongodb://localhost:27017/ami')
  .then(() => console.log('connected!'));
预设表规则并创建相应的表
// 获取设置表规则的操作对象 => schema 提要,纲要
const { Schema } = mongoose;
// 预设的表规则
const userSchema = new Schema(
  {
    name: {
      type: String,
      /* 限制字符串的长度 */
      maxLength: 10,
      minLength: 1,
  	},
    age: {
      type: Number,
      required: true, //必填
      /* 对数字大小做验证 */
	   min: 0,
	   /* 你希望给用户一个提示 */
	   max: [150, '年龄不可超过150,不要太离谱!'],
    },
    sex: {
	  type: String,
	  /* 枚举:预设字段值内容 */
	  enum: ['男', '女'],
	},
    tag: {
      type: Array,
      validate: {
        /* 校验的逻辑 */
        validator(value) {
          /* value => tag字段值 */
          /* 
             对value进行一系列的校验判断
           */
          /* 返回true或者false */
        },
        message: 'tag字段的报错信息',
      },
    },
    hobbies: String,
  },
  {
    versionKey: false, //去除版本号
  }
);
// 创建表(得到表的操作对象)
const userInfoTable = mongoose.model('userInfoTable', userSchema);
增加数据
// 增加数据 ==> 批量添加
userInfoTable
  .create(
    {
      // _id: new mongoose.Types.ObjectId(), //mongodb会帮你自动创建id域名,无需自己写
      name: '可乐',
      age: 17,
      sex: '男',
      tags: '帅气,聪明'.split(','),
      hobbies: '打篮球',
    },
    {
      // _id: new mongoose.Types.ObjectId(), //mongodb会帮你自动创建id域名,无需自己写
      name: 'ami',
      age: 161,
      sex: '男',
      tags: '帅气,聪明'.split(','),
    },
    ...
  )
  .then(() => {
    console.log('success!');
  })
  .catch(() => {
    console.log('failure');
  });
查找数据

findOne()、findById()、find()

userInfoTable
  .findOne({
    age: 161,
  })
  .then((value) => console.log(value));
 
userInfoTable
  .findById({
    _id: '6453aed985f7f27723c1999e',
  })
  .then((value) => console.log(value));

// 返回结果数组,查不到结果返回空数组
userInfoTable.find({ age: 161 }).then((value) => console.log(value));
find()之模糊查询
/* 
  模糊查询:
    => 通过条件操作符来实现

    比较查询操作符(适用于数字):
      $gt | $lt | $gte | $lte | $eq | $ne | =>  大于 | 小于 | 大于等于 | 小于等于 | 等于 | 不等于
    逻辑查询操作符(判断):
      $or | $and |$nor  => 或 | 与 | 非
    存在判断(适用于数组):
      $exists:true | false; ==> 判断是否存在某一字段名
      $in | $nin | $size ==> 判断数组长度 | $all
    
    $where 遍历数据库,由返回的boolean值决定数据的去留
    正则表达式:===> eg. find({name:/a/,})
*/
比较查询操作符的使用
userInfoTable
  .find({
    // 当值不再是一个具体的值的话,用对象的形式表示
    age: {
      // $lt: 18, //小于18
      // $lte: 18, //小于等于18
      // $gt: 18, //小于18
      // $gte: 18, //大于等于18
      // $eq: 16 //等于16
      $ne: 16, //不等于16
    },
  }) 
  .then((userArr) => console.log(userArr));
逻辑查询操作符的使用
userInfoTable
  .find({
    // 多个条件里,能满足任意一个条件的数据就是符合
    $or: [
      {
        age: {
          $gt: 16,
        },
      },
      {
        sex: '女',
      },
    ], 
	// 多个条件都要满足
	// and 用的比较少,因为find参数就符合and
	$and: [
	  {
	    age: {
	      $gt: 16,
	    },
	  },
	  {
	    sex: '女',
	  },
	],
	// 多个条件均不满足时符合
	$nor: [
	  {
	    age: {
	      $gt: 16,
	    },
	  },
	  {
	    sex: '女',
	  },
	],
  })
  .then((userArr) => console.log(userArr));
存在判断(适用于数组)以及$where的使用
userInfoTable
  .find({
    tags: {
      // 当前字段值(数组)中是否存在该值
      // $in: '帅气',
      // 当前字段值中存在任意一种值的数据就符合!!!!!!!!!!!!
      // $in: ['聪明', '帅气'],
      // 不存在
      // $nin: '帅气',
      // $nin: ['聪明', '帅气'],
    },
    hobbies: {
      // 是否存在该字段
      $exists: true,
    },
    tags: {
      // $size: 3, //数组长度为3
      $all: ['帅气', '聪明'], //数组值中存在所有条件值时才符合
    },
    // $where 遍历数据库,由返回的boolean值决定数据的去留
    $where: function () {
      // return true 表示保留该条数据 ==> 类似于过滤
      return this.age > 16;
    }, 
    name: /a/,
  })
  .then((userArr) => console.log(userArr));
find()中参数projection、options的使用
/*过滤字段:使用find()函数的第二个参数projection*/
/*处理查询的数据:使用find()函数的第三个参数options*/
userInfoTable
  .find(
    {
      $where: function () {
        return this.tags.length > 1;
      },
    },
    /* 过滤字段名 */
    {
      name: true, //只取name字段,区域字段名过滤掉
      tags: true,
      _id: false, //过滤掉该字段名,
    },
    /* 对查询到的数据进行处理 */
    {
      // 排序:降序、升序
      sort: {
        // age: 1, //升序
        age: -1, //降序
      },
      /* 跳过前n条结果 */
      skip: 6,
      /* 去除n条数据 */
      limit: 3,
      /*
        实现分页:
          12条数据,4条数据为1页

          通过skip 和 limit 配合使用
      */
    }
  )
  .then((userArr) => console.log(userArr));
删除数据 deleteMany、deleteOne

注意:

  1. 最好基于独一无二的值进行删除
  2. 数据库权限的分配(一般不太会让你有删除重要数据的权限 ==> 数据库工程师的工作)、
userInfoTable
  .deleteMany({
    age: 156,
  })
  .then((data) => {
    /*
      打印的data:{ acknowledged: true, deletedCount: 0 }
      acknowledged: 成功状态为true
      deletedCount: 成功删除了几条
    */
    console.log(data);
  });
更新(修改)数据 updateOne、updateMany、findByIdAndUpdate
  1. updateOne 修改查询到的第一条数据
  2. updateMany 修改所有查询到的数据
userInfoTable
  .updateOne(
    // 查询条件
    {
      name: '可乐',
    },
    /* 要修改成什么内容 */
    {
      /* 同时修改多个字段的值 */
      $set: {
        name: '可乐' + 1,
        age: 20,
      },
    }
  )
  .then((data) => {
    /*
      {
        acknowledged: true,
        modifiedCount: 1,
        upsertedId: null,
        upsertedCount: 0,
        matchedCount: 1
      }
    */
    console.log('更新成功', data);
  });
更新数据之对数组的更新
userInfoTable
  .updateMany(
    // 查询条件
    {
      name: '索隆1',
      tags: {
        // 元素匹配
        $elemMatch: {
          /* 存在时,会返回成员的下标 */
          $in: '五一加班',
        },
      },
    },
    /* 要修改成什么内容 */
    {
      /* 同时修改多个字段的值 */
      $set: {
        name: '索隆' + 1,
        age: 20,
      },
      /* 修改数组的值 */
      /* 
      $set: {
        // 直接覆盖 ===> 性能低
        tags: ['三刀流', '独眼'],
      }, 
      */
      /* 仅针对于数组的追加(允许添加重复值)*/
      $push: {
        /* tags: {
          // 逐项添加
          $each: ['聪明', '帅气'],
        }, */
        /* 直接添加数组 */
        tags: ['聪明', '帅气'],
      },
      /* 去重的数组追加 */
      $addToSet: {
        tags: {
          $each: ['聪明', '帅气'],
        },
      },
      /* 修改数组中指定下标的值 */
      $set: {
        'tags.2': '五一加班',
      },
      /* 删除数组中的成员 */
      $pop: {
        /* 从前面开始往后删除一个 */
        // tags:-1
        /* 从后面开始往前删除一个 */
        tags: 1,
      },
      /* 基于值,删除数组中指定成员 */
      $pull: {
        tags: '五一不加班',
      }, 
      /* 一次性删除多项成员值 */
      $pull: {
        tags: {
          $in: ['聪明', '帅气'],
        },
      }, 
      /* 删除字段(基本不用) */
      $unset: {
        sex: true,
      },
    }

    /* 获得符合条件的数组匹配数组元素的下标 */
    // {
    //   /* 经过元素匹配后,如果存在“五一加班”的成员,会返回该成员的下标存在$中 */
    //   $set: {
    //     'tags.$': '五一不加班',
    //   },
    // }
  )
  .then((data) => {
    /*
      data : {
        acknowledged: true,
        modifiedCount: 1,
        upsertedId: null,
        upsertedCount: 0,
        matchedCount: 1
      }
    */
    console.log('更新成功', data);
  });

表关联

一般是某一张表中的字段值需要是对象的时候,会新创建一个表用以关联

let scoreSchema = new Schema({
  name: String,
  subject: {
    type: String,
  },
  result: Number,
  /* 定义关联字段 */
  refStudent: {
    /* 通过唯一性的ID去关联 */
    type: mongoose.Types.ObjectId,
    // ref 关联目标表
    ref: 'student', //实际的表名
  },
});

let studentInfoTable = mongoose.model('student', studentSchema);
let scoreInfoTable = mongoose.model('score', scoreSchema);
联表查询
scoreInfoTable
  .find({
    name: '李华',
  })
  .populate({
    /* 当前表的关联字段 */
    path: 'refStudent',
    /* 关联表 */
    model: studentInfoTable,
  })
  .then((res) => {
    console.log(res);
  });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值