node中使用express+mongodb实现分页查询
文章目录
- 引言
- 一、分页案例
- 二、查询方法扩展介绍
- 1. find()
- 2. limit()
- 3. skip()
- 4. populate()
- 总结
引言
在Web应用程序开发中,分页查询是必不可少的功能之一。Node.js提供了许多优秀的工具和框架来实现分页查询,其中最流行的框架之一就是Express。同时,MongoDB也是一款非常强大的数据库管理系统,可以轻松地实现数据的存储和查询。本文将介绍如何使用Express和MongoDB来实现分页查询功能,让你的Web应用程序更加灵活和高效。无论你是初学者还是有经验的开发者,都能从本文中获益良多。
一、分页案例
首先,您需要在项目中通过npm安装 express
, mongodb
以及 mongoose
这几个模块。
$ npm install express mongoose
这是个使用 express 和 mongoose 对 MongoDB 数据库进行连接和分页查询的简单示例:
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const port = 3000;const url = 'mongodb://localhost:27017/testdb';mongoose.connect(url, { useNewUrlParser: true, useUnifiedTopology: true})
.then(() => console.log('MongoDB connected...'))
.catch(err => console.log(err))const userSchema = mongoose.Schema({name: String,email: String,
});const User = mongoose.model('User', userSchema);app.get('/users', async (req, res) => {const page = parseInt(req.query.page) || 1; // 分页数量,默认为1const size = parseInt(req.query.size) || 10; // 分页大小,默认为10const skip = (page - 1) * size;const users = await User.find().skip(skip).limit(size);res.status(200).json({users});
});app.listen(port, () => {console.log(`Server running at http://localhost:${port}`);
});
在这个例子中,我们首先通过 Mongoose 连接到本地 MongoDB 数据库,并定义了一个简单的 UserSchema。然后,我们定义了一个 ‘/’ 路由处理程序,它根据查询字符串的 ‘page’ 和 ‘size’ 参数进行分页。
app.get('/users', async (req, res) => {const page = parseInt(req.query.page) || 1; // 分页数量,默认为1const size = parseInt(req.query.size) || 10; // 分页大小,默认为10const skip = (page - 1) * size;const users = await User.find().skip(skip).limit(size);res.status(200).json({users});
});
这个服务将会在第一页上显示前10个用户(如果存在的话),在第二页上显示下一个10个用户,依此类推。您可以通过修改查询字符串中的 ‘page’ 参数来更改页面,通过修改 ‘size’ 参数来更改每页的用户数量。
注意:此处的 User 表是模拟的案例,实际使用中要将其替换为你的 MongoDB 数据库中实际的表名。
二、查询方法扩展介绍
1. find()
find()
方法在 MongoDB
中用于查询一些指定的条件,返回匹配的所有数据。你可以指定条件,或者在 find()
内部留空来搜索集合中的所有数据。
语法:
db.collection.find(query, projection)
其中:
query
:这是一个可选参数,用于通过 AND 来过滤所需 JSON 文档。projection
:这也是一个可选参数,用于通过 OR 来过滤所需 JSON 文档。
例子:
考虑一个 “students” 集合如下:
{ "_id" : 1, "name" : "Bob", "grade" : 89 }
{ "_id" : 2, "name" : "Alice", "grade" : 95 }
{ "_id" : 3, "name" : "Tom", "grade" : 85 }
如果我们想找到 grade 大于 90 的所有学生,可以这样使用 find():
db.students.find( { "grade" : { $gt : 90 } } )
这将返回:
{ "_id" : 2, "name" : "Alice", "grade" : 95 }
你也可以使用.find()方法无条件返回集合中的所有文档,只需省略查询参数即可,例如:
db.students.find()
这将返回:
{ "_id" : 1, "name" : "Bob", "grade" : 89 }
{ "_id" : 2, "name" : "Alice", "grade" : 95 }
{ "_id" : 3, "name" : "Tom", "grade" : 85 }
2. limit()
limit()
方法在 MongoDB 中用于限制返回的文档数。这个方法可以配合 skip()
方法来实现分页效果。这个方法接收一个参数,即要返回的最大记录数。
下面是一个使用的例子:
假设我们有一个叫做 orders
的集合,现在我们想要获取前 10 条订单记录。那么可以使用如下的代码:
db.orders.find().limit(10)
上面的代码会返回 orders
集合中的前 10 条文档。
如果我们想要获取第 11 到第 20 条订单记录,那么可以使用 skip()
方法来跳过前 10 条记录:
db.orders.find().skip(10).limit(10)
上面的代码会跳过 orders
集合中的前 10 条文档,然后返回接下来的 10 条文档。这样就实现了分页的效果。
3. skip()
MongoDB中的skip()
方法用于在读取数据时跳过指定数量的数据。该方法一般常配合limit()方法一同使用,适用于数据分页场景。
例如,我们有一个用户表user,并且有一个需求是每页显示10个用户,现在要获取第二页的数据。那么我们可以使用skip()和limit()方法如下:
db.user.find().limit(10).skip(10);
以上述代码为例,先调用limit(10)的目的是限制本次查找操作返回的结果数量不会超过10个,然后调用skip(10)的目的是跳过头10个结果,也就是说从第11个结果开始取。因此,该操作将返回第11个到第20个结果,即对应于数据库中的第二页的用户数据。
4. populate()
在 MongoDB 中,populate()
方法被用来获取文档的引用字段的详细信息。换句话说,它被用来替换引用文档的字段。
例子如下:
假设你有两个 MongoDB 的模型,一个是 User,一个是 Post,User 模型中的每一个用户可能有多个文章。
User 模型定义如下:
const userSchema = mongoose.Schema({_id: mongoose.Schema.Types.ObjectId,name: String,posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }]
});module.exports = mongoose.model('User', userSchema);
Post 模型定义如下:
const postSchema = mongoose.Schema({_id: mongoose.Schema.Types.ObjectId,title: String,content: String
});module.exports = mongoose.model('Post', postSchema);
如上我们可以看到,User 的模型里有一个 posts
字段,这个字段是一个数组,包含了一些 Post 的 _id
。所以,如果我们要获得一个用户以及其所有的文章的详细信息,我们就需要用到 populate()
这个方法。
User
.findOne({ name: 'John' })
.populate('posts') // 该方法替换了 `posts` 字段里的所有 Post Id 为具体的 Post 对象。
.exec((err, user) => {console.log("User: ", user); // 显示用户以及该用户的所有文章对象
});
这就是 populate()
的用法,在实际应用中,这个方法常常被用在获取关联数据的场景,非常方便且代码清晰。
注意:在 Mongoose 中,populate()
只工作在 ObjectIds 类型的字段上。同时,被引用的模型需要正确的定义及导出,否则 populate()
会找不到相应的模型从而失败。
总结
总结,在本篇博客中,我们详细探讨了如何在node.js中使用express和mongodb实现分页查询。我们首先介绍了express和mongodb的基础知识,然后我们深入讨论了如何将两者结合起来使用,实现数据的获取和分页显示。尽管实现过程可能有些复杂,但只要按照步骤操作,并充分理解每一步的意义,就能够成功实现这一功能。这不仅能提高我们的node.js开发效率,也使我们的应用具有更高的用户友好性。后面,我们还会探讨更多关于node.js和相关技术的应用,敬请期待。
相关文章:
node中使用express+mongodb实现分页查询
文章目录 引言一、分页案例二、查询方法扩展介绍1. find()2. limit()3. skip()4. populate() 总结 引言 在Web应用程序开发中,分页查询是必不可少的功能之一。Node.js提供了许多优秀的工具和框架来实现分页查询,其中最流行的框架之一就是Express。同时&…...
信创优选,国产开源。Solon v2.4.2 发布
Solon 是什么开源项目? 一个,Java 新的生态型应用开发框架。它从零开始构建,有自己的标准规范与开放生态(历时五年,已有全球第二级别的生态规模)。与其他框架相比,它解决了两个重要的痛点&…...
Java HTTP client常见库
前言 每种编程语言里最常用的库恐怕是Http请求库了,如python里的requests包,nodejs里的request模块。 在Java世界里,也是百花齐放,山头林立。常用的有: HttpURLConnection: 最早的JDK提供的类Java 11提供的HttpClien…...

【Java基础教程】(四十四)IO篇 · 上:File类、字节流与字符流,分析字节输出流、字节输入流、字符输出流和字符输入流的区别~
Java基础教程之IO操作 上 🔹本节学习目标1️⃣ 文件操作类:File2️⃣ 字节流与字符流2.1 字节输出流:OutputStream2.2 字节输入流:InputStream2.3 字符输出流:Writer2.4 字符输入流:Reader2.5 字节流与字符…...

电商数据获取:网络爬虫还是付费数据接口?
随着电商行业的迅速发展,对电商数据的需求也越来越大。在获取电商数据时,常常面临一个选择:是自己编写网络爬虫进行数据爬取,还是使用现有的付费数据接口呢?本文将从成本、可靠性、数据质量等多个角度进行分析…...
树形结构——二叉树类型
本文主要介绍树形结构中的二叉树类型,包括二叉树、平衡二叉树、二叉查找树和完全二叉树; 1.二叉树 二叉树是一种树形结构,其中每个节点最多有两个子节点,通常称为左子节点和右子节点。二叉树具有以下特点: 每个节点…...
JavaScript对象的方法与原型链
在JavaScript中,对象是一种非常重要的数据类型,它允许我们将多个属性和方法组织在一起。对象的方法和原型链是理解JavaScript中面向对象编程的关键概念。本文将详细讲解对象的方法和原型链,用通俗易懂的方式帮助你深入理解这些概念。 1. 对象…...
Oracle入门初探---第一章 批量创建表、索引并插入测试数据
Oracle系列文章目录 第一章 批量创建表并插入测试数据 文章目录 Oracle系列文章目录前言一、创建表和索引二、向表中加入数据总结 前言 使用数据库,首先要向数据库中加入大量数据,本篇文章提供了一些测试数据 一、创建表和索引 -- 创建数据库和索引 -…...
全面讲解最小二乘法
常见的最小二乘法我们就不多说了,下面主要介绍一下最小二乘法的一些先进方法。 正则化的最小二乘法 在使用常见的最小二乘法进行回归分析时,常常会遇到过拟合的问题,也就是在训练数据集上表现的很好,但是在测试数据集上表现的很…...

【阻止IE强制跳转到Edge浏览器】
由于微软开始限制用户使用Internet Explorer浏览网站,IE浏览器打开一些网页时会自动跳转到新版Edge浏览器,那应该怎么禁止跳转呢? 1、点击电脑左下角的“搜索框”或者按一下windows键。 2、输入“internet”,点击【Internet选项…...
C++/Linux项目——日志系统(简介)
一,日志系统的目的 1.⽣产环境的产品为了保证其稳定性及安全性是不允许开发⼈员附加调试器去排查问题, 可以借助⽇志系统来打印⼀些⽇志帮助开发⼈员解决问题 2.上线客⼾端的产品出现bug⽆法复现并解决, 可以借助⽇志系统打印⽇志并上传到服…...
【Redis面试题整理一】
一、Redis定义 Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,读写速度非常快,被广泛应用于缓存方向。并且,Redis 存储的是 KV 键值对数据。 二、Redis为什么不存在并发竞争 对数据类型的操作都是原子性的&a…...
前端权限验证之自定义指令v-permission
自定义指令 在前端处理按钮权限详细代码 在前端处理按钮权限 使用vue自定义指令来v-permission 来控制按钮 详细代码 //index.js文件 import permission from ./permissionconst install function(Vue) {Vue.directive(permission, permission) }if (window.Vue) {window[p…...
c++使用条件变量实现生产消费问题(跨平台)
1. 生产者线程 思路:队列满了的情况下, 触发条件变量wait, 等待消费线程消费后唤醒继续生产. void ProducerThreadFunc() {while(1) { while(/* 容器已满 */) { /* 线程等待, 直到消费者消费后唤醒继续执行 */ }/* 生产动作 */ } }2. 消…...

怎么快速搭建BI?奥威BI系统做出了表率
搭建BI系统有两大关键,分别是环境搭建和数仓建设。这两点不管是哪一个都相当地费时费力,那要怎么才能快速搭建BI平台,顺利实现全企业数字化运营决策?奥威BI系统方案,你值得拥有! 奥威BI系统方案࿰…...

Kafka3.4 SASL/kerberos/ACL 证以及 SSL 加密连接
Kafka3.4 SASL/kerberos ACL 证以及 SSL 加密连接 序 前面我们使用 kafka3.3.1 on zookeeper 的模式进行多网段监听的 kafka 集群,顺便搭建起 kafkaui 后发现一些问题,我们 kafka 集群没有连接认证,万一谁知道了我们的 kafka 连接地址&…...

UE中低延时播放RTSP监控视频解决方案
第1章 方案简介 1.1 行业痛点 在各种智慧城市、智慧社区、智慧水利、智慧矿山等数字孪生项目中,经常使用通UE来开发三维可视化场景。在这些场景中通常都需要把现场的各种监控视频在UE的可视化场景中接入,主要包含海康威视、大华、宇视、华为等众多监控…...

iOS - 开发者账号续订会员资格更换订阅的账号
文章目录 前言开发环境续订会员资格转让账户持有人验证身份1. 实名认证2. 联系信息 更换订阅的账号最后 前言 公司有一个开发者账号快到期了需要续订会员资格,刚注册时是用我自己的个人账号完成的订阅购买。现在想来有点不妥,于是尝试更换用于订阅的账号…...
大数据课程F3——HIve的基本操作
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握HIve的基本SQL语句和注意问题; ⚪ 掌握HIve的表结构; ⚪ 掌握HIve的数据类型; ⚪ 掌握HIve的基础函数和窗口函数; 一、基本SQL 1. SQL的执行方式 1. 通过hive -e的方式来执行指…...
top解析
top - 13:52:26 up 26 days, 20:56, 2 users, load average: 0.00, 0.01, 0.05 当前时间 系统运行时间,格式为时:分 当前登陆用户数2 系统负载,即任务队列的平均长度。三个数值分别为1分钟,5分钟,15分钟前到现在的平均…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...