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.bodyif(!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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

模拟器怎么代理IP?代理IP对手机设置模拟器有哪些影响?

一、代理IP的基本概念和作用流冠代理IP是一种网络服务&#xff0c;可以帮助用户隐藏自己的真实IP地址&#xff0c;通过代理服务器进行网络请求&#xff0c;从而保护用户的隐私和安全。在模拟器中&#xff0c;代理IP的作用也是如此&#xff0c;可以帮助模拟器隐藏真实的IP地址&a…

javascript 常见工具函数(一)

1.将JSON数据根据相同值&#xff0c;进行归类划分&#xff1a; var arr [{ time: "1", img: "22222" }, { time: "2", img: "555" }, { time: "1", img: "888888" }, { time: "2", img: "4444&q…

MySQL Too many connections报错

MySQL 时不时出现Too many connections报错&#xff0c;重启MySQL就好了 但是过段时间又出现 一、解决方案&#xff1a; 1.修改mysql最大连接数 set global max_connections500; 以上是修改立即生效的&#xff0c;重启MySQL就会还原回去 在MySQL配置文件修改 max_connection…

力扣刷题-二叉树-二叉搜索树中的搜索

700 二叉搜索树中的搜索 给定二叉搜索树&#xff08;BST&#xff09;的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 NULL。 例如&#xff0c; 在上述示例中&#xff0c;如果要找的值是 5&#x…

UDP单播

CMakeLists.txt文件中添加如下行&#xff1a; link_libraries(ws2_32) 1.发送端 #include <iostream> #include <winsock2.h> #include <cstdio>#pragma comment(lib, "Ws2_32.lib") // Link with ws2_32.libint main() {1.Initialize winsock…

JS 手写 new 函数

工作中我们经常会用到 new 关键字&#xff0c;new 一个构造函数生成一个实例对象&#xff0c;那么new的过程中发生了什么呢&#xff0c;我们今天梳理下 创建一个对象对象原型继承绑定函数this返回对象 先创建一个构造函数&#xff0c;原型上添加一个方法 let Foo function (n…

03、Kafka ------ CMAK(Kafka 图形界面管理工具) 下载、安装、启动

目录 CMAK&#xff08;Kafka 图形界面管理工具&#xff09;下载安装启动打开 cmak 图形界面 CMAK&#xff08;Kafka 图形界面管理工具&#xff09; Kafka本身并没有提供Web管理工具&#xff0c;而是推荐使用bin目录下各种工具命令来管理Kafka&#xff0c; 这些工具命令其实用起…

vue3中标签form插件

想写一个系统&#xff0c;对八字进行标注&#xff0c;比如格局&#xff0c;有些八字就有很多格局&#xff0c;于是就想着使用el-tag但是&#xff0c;form表单中如何处理呢&#xff1f; 这个时候&#xff0c;就需要自己写一个,modelValue是表单的默认属性 <template><…

以 Serverfull 方式运行无服务器服务

当前 IT 架构中最流行的用例是从 Serverfull 转向 Serverless 设计。在某些情况下&#xff0c;我们可能需要以 Serverfull 方式设计服务或迁移到 Serverfull 作为运营成本的一部分。 在本文中&#xff0c;我们将展示如何将 Kumologica flow 作为 Docker 容器运行。通常&#x…

HarmonyOS页面和自定义组件生命周期

页面和自定义组件生命周期 在开始之前&#xff0c;我们先明确自定义组件和页面的关系&#xff1a; 自定义组件&#xff1a;Component装饰的UI单元&#xff0c;可以组合多个系统组件实现UI的复用。页面&#xff1a;即应用的UI页面。可以由一个或者多个自定义组件组成&#xff…

52、全连接 - 特征与样本空间的对应关系

上一节说到经过全连接层之后,神经网络学习到的特征,会从隐层特征空间逐步映射到样本空间,这主要是由于全连接层可以融合全局的特征。 在经过全连接层之后,在 ResNet50 这个神经网络中会输出1000个特征的得分值,这1000个特征的得分值,便可以对应到图像的分类。 怎么对应…

居然在Web上就可以体验下苹果电脑的操作系统啦?

发现一款宝藏项目 MacOS &#xff0c;在Web上打造一款原汁原味的 MacOS系统&#xff0c;不同于以外的仿操作系统的web应用&#xff0c;该应用底层基于 HTML5的 FileSystem 和 IndexedDB 构建了文件系统&#xff0c;理论上可以基于这套系统实现任何的上层应用。作者还制定了可以…

洛谷P1024[NOIP2001 提高组] 一元三次方程求解(cpp)(二分查找)

目录 1.题目 2.思路 3.AC 1.题目 # [NOIP2001 提高组] 一元三次方程求解 ## 题目描述 有形如&#xff1a; 这样的一个一元三次方程。给出该方程中各项的系数&#xff08;a,b,c,d 均为实数&#xff09;&#xff0c;并约定该方程存在三个不同实根&#xff08;根的范围在 -…

【JavaEE进阶】 关于Spring mvc 响应

文章目录 &#x1f38d;序言&#x1f333; 返回静态⻚⾯&#x1f332;RestController 与 Controller 的关联和区别&#x1f334;返回数据 ResponseBody&#x1f38b;返回HTML代码⽚段&#x1f343;返回JSON&#x1f340;设置状态码&#x1f384;设置Header&#x1f6a9;设置Con…

【hyperledger-fabric】部署和安装

简介 对hyperledger-fabric进行安装&#xff0c;话不多说&#xff0c;直接开干。但是需要申明一点&#xff0c;也就是本文章全程是开着加速器进行的资源操作&#xff0c;所以对于没有开加速器的情况可能会由于网络原因导致下载资源失败。 资料提供 1.官方部署文档在此&#…

解密!电梯机房温差之谜

小伍&#xff1a;大家好&#xff0c;本次小伍带大家来到【电梯机房】&#xff0c;我们来先测一下温度 电梯机房【外屋】&#xff1a;23.2 度 小伍&#xff1a;好&#xff0c;我们再看里面的设备温度 电梯机房【外里】&#xff1a;74 度 523能源&#xff1a;哇塞&#xff0c;…

写了个在线 SQL 转换工具,支持 Oracle、Mysql、SQLServer 语句互转。

原本用户公司要迁移 oracle 到 mysql 上&#xff0c;数据库方言上有一定的区别&#xff0c;老的 SQL 又臭又长转起来也不太方便&#xff0c;尤其是日期类的完全无法适用&#xff0c;所以才写了这个工具&#xff1a;不同类型sql互转在线工具-开发者工具 可以用于不同数据库之间的…

XML解析神器:Apache Commons Digester

第1章&#xff1a;引言 大家好&#xff0c;我是小黑。今天咱们聊聊一个在现代编程中经常遇到的话题&#xff1a;XML解析。你可能知道&#xff0c;XML&#xff08;可扩展标记语言&#xff09;因其灵活性和可读性&#xff0c;在配置文件、数据交换等方面广泛使用。但是&#xff…

第一节 初始化项目

系列文章目录 第一节 初始化项目 文章目录 操作步骤 总结 操作步骤 打开cmd 输入 vue ui 在打开的网页中点击“创建”&#xff0c;复制文件夹路径并粘贴点击“在此创建新项目” 输入项目名称 点击下一步选择手动配置 选择babel、router、vuex、css pre-processors、 linter建…

(Linux)虚拟机配置固定IP

Linux操作系统的IP地址是通过DHCP服务获取的&#xff0c;也就是动态获取IP地址&#xff0c;每次重启设备后都会获取一次&#xff0c;会导致IP地址频繁变更&#xff0c;为了不频繁更新映射关系&#xff0c;我们需要IP地址固定下来。 1.在VM中配置IP地址网关和网段 打开虚拟网络…