Node.js | MongoDB 入门讲解 Mongoose 模块的初步应用

news2024/12/23 14:58:57

在这里插入图片描述


🖥️ NodeJS专栏:Node.js从入门到精通
🖥️ 博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)
🖥️ TypeScript知识总结:TypeScript 学习笔记(十万字超详细知识点总结)
🧑‍💼 个人简介:大三学生,一个不甘平庸的平凡人🍬
👉 你的一键三连是我更新的最大动力❤️!


📑目录

  • 🔽 前言
  • 1️⃣ 数据库类型
    • 🔹 关系型数据库
    • 🔹 非关系型数据库
    • 🔹 区别
    • 🔹 为什么选择MongoDB?
  • 2️⃣ 在命令行中操作数据库
    • 🔹 数据库操作
    • 🔹 集合操作
    • 🔹 文档操作
  • 3️⃣ Nodejs连接操作数据库
    • 🔹 创建模型
    • 🔹 数据操作
  • 🔼 结语


🔽 前言

既然我们学习了NodeJS,正式进入了后端开发的领域,那么数据库的知识就必不可少了,这篇文章我们将去学习如何在NodeJS中应用非关系型数据库MongoDB,后期也会学习如何应用关系型数据库MySql

由于本专栏是针对NodeJS的,所以本篇文章侧重于讲解NodeJS如何连接并操作MongoDB数据库,并不会对MongoDB的安装配置以及原生的操作语法做过多的讲解(这些网上已经有很多的教程了,想深入了解的可自行搜索)。

1️⃣ 数据库类型

🔹 关系型数据库

关系型数据库最典型的数据结构是,由二维表及其之间的联系所组成的一个数据组织。

结构化查询语言(Structured Query Language)简称SQL,结构化查询语言是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统

优点:

  1. 易于维护:都是使用表结构,格式一致;
  2. 使用方便:SQL语言通用,可用于复杂查询;
  3. 复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。

缺点:

  1. 读写性能比较差,尤其是海量数据的高效率读写;
  2. 固定的表结构,灵活度稍欠;
  3. 高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。

常见的关系型数据库有mysqlsqlserverdb2oracle

🔹 非关系型数据库

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。

NoSQL,泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在处理web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,出现了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,特别是大数据应用难题。

优点:

  1. 格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
  2. 速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
  3. 高扩展性;
  4. 成本低:nosql数据库部署简单,基本都是开源软件。

缺点:

  1. 不提供sql支持,这意味着我们需要额外学习专门针对非关系型数据库的查询语言,并且不同的非关系型数据库使用的语言也可能不同;
  2. 无事务处理;
  3. 数据结构相对复杂,复杂查询方面稍欠。

常见的非关系型数据库有mongodbHbaseRedis

🔹 区别

关系型和非关系型数据库的主要差异是数据存储的方式。关系型数据天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。

与其相反,非关系型数据不适合存储在数据表的行和列中,而是大块组合在一起。非关系型数据通常存储在数据集中,就像文档、键值对或者图结构。你的数据及其特性是选择数据存储和提取方式的首要影响因素。

SQL关系型数据库与MongoDB数据库的一些术语区别:

SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins表连接/MongoDB不支持
primary keyprimary key主键/MongoDB自动将_id字段设置为主键

🔹 为什么选择MongoDB?

  • 由于MongoDB独特的数据处理方式,可以将热点数据加载到内存,故而对查询来讲会非常快(当然也会非常消耗内存) ;
  • 同时由于采用了BSON的方式存储数据,故而对JSON格式数据具有非常好的支持性以及友好的表结构修改性,文档式的存储方式,数据友好可见;
  • 数据库的分片集群负载具有非常好的扩展性以及非常不错的自动故障转移。

2️⃣ 在命令行中操作数据库

🔹 数据库操作

Help查看命令提示

help
db.help()
db.test.help()
db.test.find().help()

上面是四条命令,每一行都是一条单独的命令,并不是一个整体,这里只是用这四条命令演示help的使用

创建/切换数据库

# 创建/切换到music数据库
use music

查询数据库

show dbs

查看当前使用的数据库

db
# 或
db.getName()

显示当前数据库的状态

db.status()

查看当前数据库的版本

db.version()

查看当前数据库的链接机器地址

db.getMongo()

删除数据库

db.dropDatabase()

🔹 集合操作

创建一个聚集集合

# 创建一个最大存储空间为5M,最多5000个文档的集合
db.createCollection("collName",{size:5242880,capped:true,max:5000});

得到指定名称的聚集集合

# 得到account集合
db.getCollection("account");

得到当前db的所有聚集集合

db指的就是数据库,所以是得到当前数据库的所有聚集集合

db.getCollectionNames();

显示当前db的所有聚集集合的状态

db.printCollectionStats();

删除聚集集合

# 删除users集合
db.users.drop();

🔹 文档操作

MongoDB中的一个文档就相当于是一条数据

添加

# 向users集合中添加文档
# 添加一条文档
db.users.save({name:'Ailjx',age:18,sex:true});
# 添加多条文档
db.users.save({name:'Ailjx',age:18,sex:true},{name:'Ailjx2',age:18});

修改

# 将users集合中age为25的文档的name字段修改为changeName
db.users.update({age:25},{$set:{name:'changeName'}},false,true);
# 将users集合中name为'ailjx'的文档的age字段的值加5
db.users.update({name:'ailjx'},{$inc:{age:5}},false,true);
# 将users集合中name为'ailjx'的文档的age字段的值加5并将name字段修改为A
db.users.update({name:'ailjx'},{$inc:{age:5},$set:{name:'A'}},false,true);

删除

# 删除users集合中age为132的文档
db.users.remove({age:132});
# 删除users集合中所有文档
db.users.remove({});

查询

# 查询users集合中的所有记录(文档/数据)
db.users.find();

# 查询age=22的记录
db.users.find({"age":22});
# 查询name=zhangsan,age=22的数据
db.users.find({name:'zhangsan',age:22});

# 查询name字段去重后的数据
db.users.distinct("name");

# 查询age>22的记录
db.users.find({age:{$gt:22}});
# 查询age>=22的记录
db.users.find({age:{$gte:22}});
# 查询age<22的记录
db.users.find({age:{$lt:22}});
# 查询age<=22的记录
db.users.find({age:{$lte:22}});
# 查询age>=21并且age<=26的记录
db.users.find({age:{$gte:21,$lte:26}});

# 查询name字段中包含mongo的数据(模糊查询)
db.users.find({name:/mongo/); # 使用正则
# 查询name字段中以mongo开头的数据(模糊查询)
db.users.find({name:/^mongo/);

# 查询指定列name、age数据(想显示哪列就将字段设置为1,不想显示就设置成0)
db.users.find({},{name:1,age:1);
# 查询指定列name、age且age>25的数据
db.users.find({age:{$gt:25}},{name:1,age:1);

# 按照age排序(写成数组就是多列查询)
db.users.find().sort({age:1}); # 升序
db.users.find().sort({age:-1}); # 降序

# 查询前5条数据
db.users.find().limit(5);
# 查询10条以后的数据
db.users.find().skip(10);
# 查询在5-10条之间的数据
db.users.find().skip(5).limit(5);

# or查询
db.users.find({$or:[{age:22},{age:25}]}); # 查询age=22的或age=25的数据

# 查询第一条数据
db.users.findOne();

# 查询某个结果集的记录条数
db.users.find({age:{$gte:25}}).count(); # 查询age>=25的记录共有多少条

3️⃣ Nodejs连接操作数据库

mongoose中文文档

安装Mongoose

npm i mongoose

Mongoose是一个对象文档模型(ODM)库,它对Node原生的MongoDB模块进行了进一步的优化封装,并提供了更多的功能。

Nodejs中引用Mongoose

// 引入Mongoose
const mongoose = require("mongoose");

// 连接数据库
// 前缀mongodb:是固定的,后面是你的mongodb的运行端口(默认是127.0.0.1:27017)
// server_test代表数据库名称
mongoose.connect("mongodb://127.0.0.1:27017/server_test");

// 当你插入集合和数据时,数据库server_test会自动创建

🔹 创建模型

创建的这个模型主要就是用来定义一个集合的结构(集合的文档具有哪些字段以及其对应的数据类型)

// UserModel.js
const mongoose = require("mongoose");

const Schema = mongoose.Schema

// 字段类型
const UserType = {
    username: String,
    password: String,
    age: Number,
};

// 创建一个模型(user),对应数据库中的集合(表)(users)
const UserModel = mongoose.model("user", new Schema(UserType));
// 注意:创建的mongodb的集合名称是加s的
// mongoose.model第二个参数可以通过mongoose.Schema生成的实例来限制集合字段类型
// 因为mongodb过于自由,对类型没有限制,我们在开发中往往需要使用mongoose.Schema来手动限制数据库各种字段类型
module.exports = UserModel;

这个模型我们起名为UserModel,定义了一个存放用户信息的集合users,包含usernamepasswordage三个字段。

当我们引入这个模型进行插入数据后,server_test数据库中就会自动创建users集合用来存放我们插入的数据。

注意: 我们在代码中指定的是"user",但MongoDB实际创建的集合是users(会自动加上s)。

🔹 数据操作

mongoose为我们提供了很多的api,大家可去mongoose中文文档进行查阅:

在这里插入图片描述

这里只演示部分api的应用:

添加数据:

// 引入对应的模型
const UserModel = require("../model/UserModel");

// 插入数据库
UserModel.create({ username:'Ailjx', password:'11111', age:18 })
    .then((data) => {
        // ...
    })
    .catch((error) => {
        console.log(error);
        // ...
    });

对模型的操作是异步的(promise),支持then回调来捕捉成功的状态,catch回调捕捉失败的状态。

删除数据:

// 引入对应的模型
const UserModel = require("../model/UserModel");

// 删除数据
// deleteOne删除一条数据
UserModel.deleteOne({ _id: '44'})
    .then((data) => {
        // ...
    })
    .catch((error) => {
        console.log(error);
        // ...
    });

更新数据:

// 引入对应的模型
const UserModel = require("../model/UserModel");

// 更新数据
// updateOne更新一条数据
UserModel.updateOne(
    { _id: '444'},
    {
        username:'1',
        password:'1',
        age:18,
    }
)
    .then((data) => {
        // "更新成功!"
    })
    .catch((error) => {
        console.log(error);
        // "更新失败!" 
    });

查询数据:

// 引入对应的模型
const UserModel = require("../model/UserModel");

UserModel.find()
    .count() // count方法,获取数据数量
    .then((dataCount) => {
        // find查询,第二个参数数组指定获取的字段,这里是获取username和age以及id(默认具有),不获取password
        UserModel.find({}, ["username", "age"])
            // sort排序,按照age:1(正序)排序,age:-1为倒叙
            .sort({ age: 1 })
            // skip方法,代表跳过几条数据开始获取
            .skip(10)
            // limit方法,代表取多少条数据
            .limit(5)
            .then((data) => {
                // 查询成功
            });
    });

🔼 结语

博主的Node.js从入门到精通专栏正在持续更新中,关注博主订阅专栏学习Node不迷路!

如果本篇文章对你有所帮助,还请客官一件四连!❤️

在这里插入图片描述

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

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

相关文章

【测试沉思录】10. 我们用到的3种Mock测试方案

欢迎订阅我的新专栏《现代命令行工具指南》&#xff0c;精讲目前最流行的开源命令行工具&#xff0c;大大提升你的工作效率。 作者&#xff1a;王媛媛 编辑&#xff1a;毕小烦 Mock 这个词对于测试人员来说并不陌生&#xff0c;当我们要测试的接口 A 依赖接口 B &#xff0c;可…

CSS3专题-[上篇]:过渡、2D转换、动画

目录 CSS3&#xff1a;前置特性 CSS3&#xff1a;盒子模型 CSS3&#xff1a;图片滤镜与模糊处理 blur()&#xff1a;高斯模糊 CSS3&#xff1a;计算盒子宽度calc()函数 CSS3&#xff1a;过渡效果 transition属性 2D转换&#xff1a;transform属性 translate()方法 * t…

11、Microsoft Visual Studio 2022 Installer Projects踩坑一

前言&#xff1a;VS自带的打包工具对于单文件简单程序很好用&#xff0c;对于多文件涉及到依赖其他程序就需要多一点配置了&#xff0c;之前打包过一个简单程序&#xff0c;后来程序变大后再执行生成的时候就出现问题了&#xff0c;要么执行不成功&#xff0c;要么生成成功安装…

猿创征文|后端开发工程师提升开发效率神器推荐

简介 对于现在的后端工程师来说&#xff0c;并不仅仅局限于编写代码和解决bug&#xff0c;这两个要素了。如果你目前还只是忙碌的写代码和改bug的话&#xff0c;那要深度思考一下&#xff0c;我为什么日复一日的写这些重复代码&#xff1f;这样有何意义&#xff1f;或者说&…

Java开发必须掌握的运维知识 (七)-- 性能监控日志收集,数据实时分析存储工具Influxdb实战

从这节起&#xff0c;我们要循序渐进的学习InfluxDB、Cadvisor、Grafana。这三种工具组合使用可以完成对容器的各项指标实时监控&#xff0c;也为后面的k8s打好基础。 一、InfluxDB的介绍 InfluxDB是一种用Go编写的时间序列数据库&#xff0c;主要用来存储一些时间序列的数据…

项目管理之沟通管理

目录 前言 一、沟通模型是什么&#xff1f; 二、项目沟通管理过程 三、规划沟通管理 1.规划沟通管理的ITO 2.工具与技术的使用 四、管理沟通 1.管理沟通的ITO 2.三种绩效区别 五、控制沟通 1.控制沟通的ITO 2.工具与技术的使用 总结 前言 本文章主要介绍以下项目…

JVM垃圾回收——三色标记法

目录 一、什么是三色标记 二、三色标记的过程 三、三色标记的缺点 四、垃圾回收机如何弥补三色标记的缺点 在CMS、G1这种并发的垃圾收集器收集对象时&#xff0c;假如一个对象A被GC线程标记为不可达对象&#xff0c;但是用户线程又将A对象标记为可达对象&#xff0c;那么此…

基于Session实现短信登录

目录 一、基于Session实现登录 1.1 业务流程图​编辑 二、发送短信验证码 2.1 发送短信请求方式及参数说明 2.2 业务层代码模拟发送短信 三、登录功能 3.1 短信验证的请求方式及路径 3.2 业务层代码实现用户登录 3.3 拦截器——登录验证功能 三、隐藏用户敏感信息 …

React-Hooks源码深度解读

useState 解析 useState 使用 通常我们这样来使用 useState 方法 function App() {const [num, setNum] useState(0);const add () > {setNum(num 1);};return (<div><p>数字: {num}</p><button onClick{add}> 1 </button></div>…

前Zynga中国总裁田行智联合创办的亚创拟上市:市值25亿美元 公司PPT曝光

雷递网 雷建平 10月31日前Zynga中国总裁田行智&#xff08;Andy Tian&#xff09;联合创办的亚洲创新集团&#xff08;Asia Innovations Group Limited&#xff0c;简称“亚创集团”&#xff09;日前拟通过SPAC模式上市。亚创集团已与特殊目的收购公司&#xff08;SPAC&#xf…

【C++】内联函数auto关键字基于范围的for循环指针空值nullptr

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;内联函数…

Bitquery与Moonbeam集成,为多链提供链上数据访问

Moonbeam是一个智能合约平台&#xff0c;用于构建跨链互连应用程序&#xff0c;能够访问任何链上的用户、资产和服务。通过将来自以太坊、Cosmos、波卡等功能整合到一个平台中。近日&#xff0c;Moonbeam与Bitquery集成&#xff0c;为市场分析、资金流、DeFi等多链提供链上数据…

JavaScript 53 JavaScript 箭头函数

JavaScript 文章目录JavaScript53 JavaScript 箭头函数53.1 语法53.2 this 怎么办&#xff1f;53.2.1 常规函数53.2.2 箭头函数53.3 浏览器支持53 JavaScript 箭头函数 ES6 中引入了箭头函数。 箭头函数允许我们编写更短的函数 53.1 语法 以前定义函数 hello function() …

一位小镇做题家的付费咨询

前几天&#xff0c;有位知乎读者咨询我&#xff0c;感觉很迷茫&#xff0c;不知道做什么。这可能也是大多数在校大学生的状态&#xff0c;忙忙碌碌&#xff0c;浑浑噩噩&#xff0c;不知道该怎么办。 首先&#xff0c;不管从事哪个行业&#xff0c;你的学历一定是亮点。专业的话…

Flutter ChoiceChip 用来实现选择标签效果

程序员如果敲一会就停半天&#xff0c;抱着一杯茶&#xff0c;表情拧巴&#xff0c;那才是在编程&#xff0c;在之前我要实现一级标签效果&#xff0c;我还在苦苦写了好多嵌套的代码&#xff0c;当我看到 Clip 时&#xff0c;泪奔啊&#xff0c;原来一个组件就可以实现&#xf…

(8个方法)解决windows11/10/8/7卡在准备就绪一直转圈

许多用户会遇到Win10安装卡在准备就绪一直转圈的情况或者重装系统准备就绪转圈的问题。也有一些用户反映&#xff0c;Win10准备就绪后黑屏重启&#xff0c;一直循环。一开始大家会耐心等待&#xff0c;但是等了很久后发现没什么用&#xff0c;这该怎么办&#xff1f;本文教你一…

第32讲:MySQL数据库的体系结构组成

MySQL数据库的体系结构组成 MySQL数据库整个体系结构可以分为五个部分,如下图所示: 1)客户端连接器 这一层也是整个MySQL体系中的最上层,包含本地Sock通信和支持大多数客户端到服务端的TCP通信,像JAVA的JDBC、Python、PHP都可以连接到MySQL数据库。 2)数据库连接层 客…

嵌入式分享合集92

一、常用电路基础公式 1.欧姆定律计算 计算电阻电路中电流、电压、电阻和功率之间的关系。 欧姆定律解释了电压、电流和电阻之间的关系&#xff0c;即通过导体两点间的电流与这两点间的电势差成正比。说明两点间的电压差、流经该两点的电流和该电流路径电阻之间关系的定律。该…

2022年了,软件测试已经饱和了?

这个年头找工作跟找对象一样难&#xff0c;咳咳&#xff0c;工作对象都木有&#xff0c;双重打击5555。 关于今年的就业市场&#xff0c;很多人表示特别惨淡&#xff0c;以往简历一投就有大批企业来联系&#xff0c;今年自己投递一大堆简历出去&#xff0c;可能全部都是已读不…

链路状态路由协议OSPF——理解OSPF多区域原理

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.OSPF的多区域 1.OSPF概述 2.生成OSPF多区域的原因 二.OSP…