express+mongoDB开发入门教程之mongoose使用讲解

系列文章

  • node.js express框架开发入门教程
  • express+mongoDB开发入门教程之mongoDB安装
  • express+mongoDB开发入门教程之mongoose使用讲解

文章目录

  • 系列文章
  • 前言
  • 一、Mongoose是什么?
  • 二、Mongoose安装
    • 三、Mongoose在express项目中使用
    • 步骤一、连接mongoDB数据库
    • 步骤二、建立模型
    • 步骤三、增删改查操作
      • 1、 新增数据
      • 2、更新数据
      • 3、删除数据
      • 4、查找数据
          • 筛选条件
            • 1、运算符(><=!==)
            • 2、枚举值 $in
            • 3、逻辑运算$or/and
            • 4、正则匹配
            • 5、排序sort
            • 6、限制个数limit
            • 7、跳过个数skip
            • 8、设置数据返回字段select
            • 9、查询总数量count
        • demo演示:


前言

      本文将讲述Mongoose的入门开发教程,以及通过一些示例演示对mongoDB数据库的增删改查操作。


一、Mongoose是什么?

      Mongoose是一个强大的Node.js库,它提供了对MongoDB数据库的操作,有了Mongoose实际开发中对MongoDB增删改查将变得很容易。

二、Mongoose安装

npm install mongoose -S

目前mongoose最新版本是v8.0,要求安装node v16以上版本,不同的mongoose版本一些api使用方式是有区别的,8.0操作上把旧版本的回调函数改成promise( aysnc/await)形式


三、Mongoose在express项目中使用

在项目根目录新建model文件夹放置Mongoose相关文件,model目录下新建db.js文件

在这里插入图片描述

步骤一、连接mongoDB数据库

假设连接到名为system数据库

db.js文件写入

const mongoose = require("mongoose");
//数据库连接地址+数据库名称(system)
const DBURL='mongodb://127.0.0.1:27017/system'
//连接数据库
 mongoose.connect(DBURL).then(res=>{
    console.log('连接成功')
 }).catch(e=>{
    console.log('连接失败')
 })
 
module.exports = mongoose;

通过API mongoose.connect 连接数据库,其中system为想要连接的数据库名称,返回值Promise,通过then/catch或async/await监听连接失败或成功。当然也可以通过监听连接事件connected和error来判断,需要注意的是数据库名即使不存在也能连接成功,在mongoDB中不存在的库或者集合在进行数据添加操作的时候会自动生成,最后导出mongoose供后续创建模型使用。

连接成功与否也可以通过监听连接事件:

 mongoose.connection.on('connected',()=>{
    console.log('数据库连接成功')
})

mongoose.connection.on('error',err=>{
    console.log('数据库连接失败')
})

其他连接事件还有:

  • connecting:初始连接时发出
  • open:在所有该连接的模型上执行 ‘connected’ 和 onOpen 后发出
  • disconnecting:断开连接发出
  • close:成功关闭连接
  • reconnected:重新连接成功发出

步骤二、建立模型

模型可以理解成每个文档字段配置,建立模型就是对字段属性进行设置,生成一个模型对象,后续增删改查操作将基于该模型对象进行方法调用

假设现在有个管理后台要存储用户信息,信息包括姓名、年龄、性别3个字段,集合名称为user
在model目录下新建user.js文件

在这里插入图片描述
写入:

const db = require("./db");

//定义结构
let userSchema = db.Schema(
  {
    name: {
      type:String,
      required:true
    },
    age: Number,
    sex: {
      type:String,
      default:'未知'
    },
  },
  { versionKey: false }//隐藏_v字段
);

//创建模型
let userModel = db.model("user", userSchema, "user");

module.exports = userModel;

在这里插入图片描述

先通过mongoose.Schema定义文档字段配置,再调用mongoose.model生成模型对象,最后导出模型对象供增删改查操作使用

mongoose.Schema 类似vue props可以设置字段类型、是否必填、默认值等

type:有效类型有如下:

  • 字符串 String
  • 数字 Number
  • 日期 Date
  • 缓冲 Buffer
  • 布尔值 Boolean
  • 混合 Schema.Types.Mixed
  • ObjectId Schema.Types.ObjectId
  • 数组 []
  • 十进制 128 Schema.Types.Decimal128
  • 映射 Map
  • 结构 subSchema
  • UUID Schema.Types.UUID
  • BigInt BigInt

required:是否必填true/false
default:默认值

     需要注意的是我们发现上面代码db.model(“user”, userSchema, “user”)生成模型时候传入3个参数其中第一个和第三个参数都是user。user为要操作的集合(表)名称,如果不设置第三参数类似db.model(“user”, userSchema)最终操作的是users集合,因为mongoose会默认在参数后面加s,实际变成users,好在提供第三个参数,我们可以通过第三个参数设置真实集合名称。
     给集合添加一个新文档默认会生成_id和_v字段,想要隐藏_v字段可以设置 versionKey: false

除了以上几个属性还有更多配置属性可以查看官网SchemaType

步骤三、增删改查操作

增删改查操作都是基于步骤二导出的模型进行函数调用,常用的命令可以总结如下表所示

API说明
Model.create()新增一条数据
Model.deleteOne()删除一条数据
Model.deleteMany()删除多条数据
Model.updateOne()修改一条数据
Model.updateMany()修改多条数据
Model.find()查找满足条件所有数据
Model.findOne()查找满足条件第一条数据
Model.findById()通过id查找一条数据
Model.findOneAndUpdate()查找一条数据修改并返回

下面所有示例将在routers/users.js文件内进行编写,该路由前缀为users,并在app.js注册,模型userModel由上面步骤二所创建

1、 新增数据

方法一:Model.create()

//导入模型
var userModel = require("../model/user");

//新增接口
router.post("/create", async (req, res) => {
  try {
    await userModel.create({ name:'李磊', age:20, sex:'男' });
    res.send({
      code: 200,
      msg: "success",
    });
  } catch (e) {
    res.send({
      code: 500,
      msg: e.message || "fail",
    });
  }
});

方法二:Document.save()

//导入模型
const userModel = require("../model/user");

//新增接口
router.post("/create", async (req, res) => {
  try {
    let doc=new userModel({ name:'李磊', age:20, sex:'男' })
    await doc.save()
    res.send({
      code: 200,
      msg: "success",
    });
  } catch (e) {
    res.send({
      code: 500,
      msg: e.message || "fail",
    });
  }
});

请求接口:

在这里插入图片描述

数据库数据:

在这里插入图片描述

动态获取新增参数示例:

//导入模型
const userModel = require("../model/user");
//新增接口
router.post("/create", async (req, res) => {
 //获取请求参数,请求数据为json格式
  let { name, age, sex } = req.body;  
  try {
    await userModel.create({ name, age, sex });
    res.send({
      code: 200,
      msg: "success",
    });
  } catch (e) {
    res.send({
      code: 500,
      msg: e.message || "fail",
    });
  }
});

执行新增请求:

在这里插入图片描述

数据库数据

在这里插入图片描述
ps:上面请求新增时候我们并没有传sex值,由于在创建模型时候sex设置了默认值为"未知"所以当请求没有传值默认保存为"未知",并且数据库默认会为每条数据创建一个_id字段作为唯一标识

2、更新数据

更新单条数据:

例如:修改李磊年龄为22岁

 userModel.updateOne({ name: "李磊" }, { age: 22 });

更新多条数据

例如:修改所有年龄为22岁的用户为男性

 userModel.updateMany({ age: 22 }, { sex:"男性" });

动态传参更新

通过传入id,更新其他字段值

//导入模型
const userModel = require("../model/user");
//更新
router.post("/update", async (req, res) => {
  let {id,name,age,sex}=req.body
  if(!id){
    res.send({
      code: 500,
      msg: "id不能为空",
    });
    return;
  }

  try {
   await userModel.updateOne({ _id: id }, {name,age,sex });
    res.send({
      code: 200,
      msg: "success",
    });
  } catch (e) {
    res.send({
      code: 500,
      msg: e.message || "fail",
    });
  }
});

接口请求测试
修改李磊年龄为100,性别为女

在这里插入图片描述

数据库数据:

在这里插入图片描述

ps:Model.updateOne/Many(condition,newVal),第一个参数为查询条件,为对象可以设置多个属性,第二个为更新的值也是个对象可以设置多个属性

3、删除数据

删除单条
例如:删除李磊用户

  userModel.deleteOne({ name: "李磊" });

删除多条

例如:删除所有男性用户

  userModel.deleteMany({ sex: "男性" });

4、查找数据

查找单条数据:

 let data=await userModel.findOne({ sex: "男性" });//查找第一条性别为男的数据
 let data2=await userModel.findById("6594c18f112053f96104b7a1");//通过id查找数据

查找所有满足条件数据

//查找年龄为10岁,性别为男性的所有数据
let data=await userModel.find({age:10, sex: "男性" });
筛选条件

增加筛选条件方法比较多,这里就挑一些比较常用讲解

1、运算符(><=!==)
  //查找年龄大于10岁,小于30岁数据
 let data=await userModel.find({age:{$gt:10,$lt:30}});

也可以用链接语法构建查询

 let data=await userModel.find().where('age').gt(10).lt(33).exec();

上面两句是等价的。

所有运算符如下:

运算符说明
$gt大于>
$gte大于等于>=
$lt小于<
$lt小于等于<=
$ne不等于!=
2、枚举值 $in
//查找性别为男性或男或未知的所有数据
  let data=await userModel.find({ sex: { $in: ['男性','男','未知'] }});

链接语法构建查询

let data=await userModel.find().where('sex').in(['男性','男', '未知']);
3、逻辑运算$or/and
//查找年龄为10岁或者20岁数据
  let data=await userModel.find({$or: [{age:10}, {age:20}]});
//查找年龄为10岁且为男性数据
  let data=await userModel.find({ $and: [{age:10}, {sex:"男性"}]});
4、正则匹配
//查找名字带小的所有数据
  let data=await userModel.find({name://});
5、排序sort
//查找所有数据按年龄正序排序返回
  let data=await userModel.find().sort({ age: 1 });
//查找所有数据按年龄倒序排序返回
  let data=await userModel.find().sort({ age: -1 });

ps:1正序,-1倒序

6、限制个数limit
//返回10个数据
  let data=await userModel.find().limit(10);
7、跳过个数skip
//跳过前100个返回第101-110位置数据
  let data=await userModel.find().skip(100).limit(10);
8、设置数据返回字段select
//返回数据只有name、age字段
  let data=await userModel.find().select('name age');
9、查询总数量count
//返回数据总个数
  let data=await userModel.find().count();//2
demo演示:

下面结合开发实际场景写一个例子来演示下筛选条件使用

在这里插入图片描述

假设我们要实现上面一个列表页,其中姓名支持模糊搜索,带分页功能

var express = require("express");
var router = express.Router();
//导入模型
const userModel = require("../model/user");

//分页查询接口
router.post("/findByPage", async (req, res) => {
  let { name, age, sex, page, size } = req.body;
  //查询参数过滤掉值为undefined或null或空值属性
  let params = Object.entries({ name, age, sex }).reduce((prev, cur) => {
    let [key, value] = cur;
    if (value!==undefined&&value!==null&&value!=='') {
      if (key === "name") {
        //名字模糊搜索正则处理
        prev[key] = new RegExp(value);
      } else {
        prev[key] = value;
      }
    }
    return prev;
  }, {});


  try {
    let query = userModel.find(params);
    if (page && size) {
      //获取分页数据
      query.skip((page - 1) * size).limit(size);
    }
    let data = await query.exec();//分页数据
    let total= await userModel.find(params).count();//总条数
    res.send({
      code: 200,
      data,
      total,
      msg: "success",
    });
  } catch (e) {
    res.send({
      code: 500,
      msg: e.message || "fail",
    });
  }
});

现有数据库数据:

在这里插入图片描述

测试请求数据

1.分页在这里插入图片描述
2.模糊搜索
在这里插入图片描述
3.其他
在这里插入图片描述

ps:查询条件某字段值如果是undefined或者空值''或者null条件参数JSON对象要过滤掉该属性否者查出来数据为空

至此最基本入门技能——增删改查操作已经介绍完,更多细节、技巧和api请查阅官方文档 https://mongoose.nodejs.cn/docs/queries.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/292388.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

游戏缺少emp.dll详细修复教程,快速解决游戏无法启动问题

在现代游戏中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“emp.dll丢失”。emp.dll是一个动态链接库文件&#xff0c;它包含了许多程序运行所需的函数和数据。当一个程序需要调用这些函数时&#xff0c;系统会从emp.dll文件中加载相应的内容。因此&#x…

Maven简介及环境搭建和基本使用(Java开发中的实用工具)

一、概述 Maven 是 Apache 软件基金会的一个开源项目,是一个优秀的项目构建工具,它 用来帮助开发者管理项目中的 jar,以及 jar 之间的依赖关系、完成项目的编译、 测试、打包和发布等工作。 Maven的相关概念 pom.xml文件&#xff1a;里面可以配置相关信息&#xff0c;指导ma…

Mac内心os:在下只是个工具,指望我干人事?

呜呜呜&#xff0c;今天去医院看病了&#xff0c;乌央央的好多人。最近在研究苹果开发者工具中的HealthKit&#xff0c;等我研究透给大家安利。今天还是继续闲聊吧&#x1f602;&#x1f602;提前感谢大家体谅我这个病号&#xff0c;发射小红心&#xff0c;biubiubiu~ 据说&am…

uniapp 无限级树形结构面包屑、单选-多选、搜索、移除功能插件,基于【虚拟列表】高性能渲染海量数据,加入动态高度、缓冲区

hyq-tree-vtw 无限级树形结构面包屑、单选-多选、搜索、移除功能 示例项目 单选-user 单选-任意一项 多选-关联下级 多选-任意一项 已选择数据弹框 说明 本插件需要使用uni-popup、uni-transition用于已选择数据弹框&#xff0c;因此需要有这些依赖,请自行导入本插件基于【虚…

vue-mixins混入处理

定义 mixins&#xff08;混入&#xff09;&#xff1a;一种分发 Vue 组件中可复用功能的非常灵活的方式&#xff0c;mixins 是一个 js 对象&#xff0c;它可以包含我们组件script中的任意功能选项&#xff0c;如&#xff1a;data、components、methods、created、computed 等等…

202365读书笔记|《温暖和百感交集的旅程》——时间帮助着一个人的一生在几千字的篇幅里栩栩如生

202365读书笔记|《温暖和百感交集的旅程》——时间帮助着一个人的一生在几千字的篇幅里栩栩如生 我能否相信自己温暖和百感交集的旅程前言和后记 《温暖和百感交集的旅程》作者余华&#xff0c;之前读完的一本书&#xff0c;已经不太记得内容了&#xff0c;看着笔记整理的这篇书…

Java项目:109SpringBoot超市仓管系统

博主主页&#xff1a;Java旅途 简介&#xff1a;分享计算机知识、学习路线、系统源码及教程 文末获取源码 一、项目介绍 超市仓管系统基于SpringBootMybatis开发&#xff0c;系统使用shiro框架做权限安全控制&#xff0c;超级管理员登录系统后可根据自己的实际需求配角色&…

Tectum:BTC L2终极解决方案+最快区块链,表现强势开启质押

随着加密市场的不断成长&#xff0c;不管是金融属性还是使用体验都有了质的提升&#xff01;牛市即将到来&#xff0c;多个机构的比特币 ETF 正在申请中&#xff0c;无论什么时候获得 SEC 的批准&#xff0c;都将为加密市场带来万亿级别的资金&#xff0c;同时吸引更多的 Web2 …

大数据 MapReduce是什么?

在Hadoop问世之前&#xff0c;其实已经有了分布式计算&#xff0c;只是那个时候的分布式计算都是专用的系统&#xff0c;只能专门处理某一类计算&#xff0c;比如进行大规模数据的排序。 很显然&#xff0c;这样的系统无法复用到其他的大数据计算场景&#xff0c;每一种应用都…

会声会影2023如何实现自定义尺寸MP4格式视频制作 会声会影视频制作过程 会声会影免费吗

在使用会声会影生成视频时&#xff0c;默认提供了很多不同的尺寸参数&#xff0c;但有些时候&#xff0c;我们需要自定义生成的尺寸&#xff0c;同时保证生成文件的格式为mp4.视频的体积不能过大&#xff0c;这时候我们要如何做呢&#xff1f;今天来介绍2个方法&#xff0c;供大…

72.乐理基础-打拍子-加延音线的节奏型

什么是延音线看这里&#xff1a;乐理基础-音符的组合方式-延音线 上一个内容&#xff1a;71.乐理基础-打拍子-三连音的变体-CSDN博客 为了让二八、四十六、前八后十六、前十六后八、前附点、后附点、小切分、大附点、大切分、三连音这是个基础节奏型产生更丰富的节奏形态&…

分享10篇优秀论文,涉及图神经网络、大模型优化、表格分析

引言 第38届AAAI人工智能年度会议将于2024年2月在加拿大温哥华举行。今天给大家分享十篇AAAI2024论文&#xff0c;主要涉及图神经网络&#xff0c;大模型幻觉、中文书法文字生成、表格数据分析、KGs错误检测、多模态Prompt、思维图生成等。 论文获取方式&#xff0c;回复&am…

【Linux驱动】Linux中断(二)—— 按键中断驱动

前一篇已经在设备树的 gpio-led 节点中引入了中断信息&#xff0c;接下来将通过API来获取设备树中的中断信息。gpio-led 节点具体内容如下&#xff1a; gpio-key0 {pinctrl-names "default";pinctrl-0 <&pinctrl_gpio_keys>; // pinctrl子系…

计算化学顶刊封面!玻色量子联合上海交大张健课题组发表量子计算重要成果

​2023年12月13日&#xff0c;北京玻色量子科技有限公司&#xff08;以下简称“玻色量子”&#xff09;联合上海交通大学在中科院分区1区、计算化学领域Top刊物JCTC&#xff08;Journal of Chemical Theory and Computation&#xff09;内刊的封面上发表了以“Encoding Molecul…

【Spring】AOP原来如此

AOP概述 什么是AOP的技术&#xff1f; 在软件业&#xff0c;AOP为Aspect Oriented Programming的缩写&#xff0c;意为&#xff1a;面向切面编程AOP是一种编程范式&#xff0c;隶属于软工范畴&#xff0c;指导开发者如何组织程序结构AOP最早由AOP联盟的组织提出的,制定了一套…

vercel部署Gemini pro

一、注册一个vercel账号&#xff08;这个东西类似于第三方的github pages&#xff0c;能部署github中的项目&#xff09; 二、注册结束后&#xff0c;填写github的账号&#xff08;需要事先在该github账号中fork一个gemini的repository&#xff09; 三、babaohuang/GeminiPro…

Koordinator 助力云原生应用性能提升:小红书混部技术实践

作者&#xff1a;宋泽辉&#xff08;小红书&#xff09;、张佐玮&#xff08;阿里云&#xff09; 编者按&#xff1a; Koordinator 是一个开源项目&#xff0c;是基于阿里巴巴内部多年容器调度、混部实践经验孵化诞生&#xff0c;是行业首个生产可用、面向大规模场景的开源混…

layuiadmin新建tabs标签页,点击保存,打开新的标签页并刷新

用的layuiamin前端框架 需求&#xff1a;新增的页面为一个标签页&#xff0c;保存后&#xff0c;需要刷新列表 1、新建customMethod.js文件&#xff0c;自定义自己的方法 layui.define(function (exports) {var $ layui.$var customMethod {// 表单点击保存后&#xff0c;…

解决docker容器内无法连接宿主redis

背景 小程序的发短信服务挂了&#xff0c;随查看日志&#xff0c;该报错日志如下 Error 111 connecting to 127.0.0.1:6379. Connection refused. 6379是监听redis服务的端口&#xff0c;那大概是redis出错了。 首先查看了redis是否正常启动&#xff0c;检查出服务正常。 由于小…

Docker-Compose部署Redis(v7.2)主从模式

文章目录 一、前提准备1. redis配置文件2. 下载redis镜像3. 文件夹结构 二、docker-compose三、主从配置1.主节点配置文件 环境 docker desktop for windows 4.23.0redis 7.2 一、前提准备 1. redis配置文件 因为Redis 7.2 docker镜像里面没有配置文件&#xff0c;所以需要…