【MongoDB】MongoDB查询语句find的使用,和提高查询速度的游标的使用,非常详细!!!

news2024/11/17 11:35:48

在这里插入图片描述

😁 作者简介:一名大四的学生,致力学习前端开发技术
⭐️个人主页:夜宵饽饽的主页
❔ 系列专栏:MongoDB数据库
👐学习格言:成功不是终点,失败也并非末日,最重要的是继续前进的勇气

​🔥​前言:

这里是关于MongoDB中查询语句find的使用,其中对于特定类型的查询非常特别,还有游标的使用可以加快我们的查询速度,这是我的学习MongoDB笔记,希望可以帮助到大家,欢迎大家的补充和纠正

文章目录

  • 第4章 查询
    • 4.1 find简介
      • 4.1.1 指定要返回的键
    • 4.3 特定类型查询
      • 4.3.3 查询数组之$slice操作符
      • 4.3.5 查询数组之数组与范围查询的相互作用
    • 4.4 $where查询
    • 4.5 游标
      • 4.5.1 limit,skip和sort
      • 4.5.2 避免略过大量结果
      • 4.5.3 游标生命周期

第4章 查询

4.1 find简介

4.1.1 指定要返回的键

概念:find方法中的第二个参数就是投影条件,投影条件是一个文档,其中键是要包含或排除的字段,对应的值为 1 表示包含,0 表示排除。默认情况下,如果不指定投影条件,MongoDB 会返回文档中的所有字段
案例:

  1. 默认情况下,如果不指定投影条件,MongoDB 会返回文档中的所有字段
> db.users.find({}, {"username" : 1, "email" : 1})
{
    "_id" : ObjectId("4ba0f0dfd22aa494fd523620"),
    "username" : "joe",
    "email" : "joe@example.com"
}

2.可能在文档中有很多键,而你不希望结果中包含 “fatal_weakness” 键:

> db.users.find({}, {"fatal_weakness" : 0})

3.要将“_id“键从返回结果剔除

> db.users.find({}, {"username" : 1, "_id" : 0})
{
    "username" : "joe"
}

4.3 特定类型查询

4.3.3 查询数组之$slice操作符

注意点:除非特别指定,否则在使用 “$slice” 时会返回文档中的所有键。这与其他的键指定符不同,后者不会返回未指定的键。例如,有这样一个关于博客文章的文档:
例子:

{
    "_id" : ObjectId("4b2d75476cc613d5ee930164"),
    "title" : "A blog post",
    "content" : "...",
    "comments" : [
        {
            "name" : "joe",
            "email" : "joe@example.com",
            "content" : "nice post."
        },
        {
            "name" : "bob",
            "email" : "bob@example.com",
            "content" : "good post."
        }
    ]
}

> db.blog.posts.findOne(criteria, {"comments" : {"$slice" : -1}})
{
    "_id" : ObjectId("4b2d75476cc613d5ee930164"),
    "title" : "A blog post",
    "content" : "...",
    "comments" : [
        {
            "name" : "bob",
            "email" : "bob@example.com",
            "content" : "good post."
        }
    ]
}

即使title和content没有显式地被包含在键指定符中,但它们依然被返回了

4.3.5 查询数组之数组与范围查询的相互作用

文档中的标量(非数组元素)必须与查询条件中的每一条子句相匹配。如果使用 {“x” : {“ g t " : 10 , " gt" : 10, " gt":10,"lt” : 20}} 进行查询,那么 “x” 必须同时满足大于 10 且小于 20。然而,如果文档中的 “x” 字段是一个数组,那么当 “x” 键的某一个元素与查询条件的任意一条语句相匹配(查询条件中的每条语句可以匹配不同的数组元素)时,此文档也会被返回。
接下来我们可以来看一个例子:
现在有一个文档

{"x" : 5}
{"x" : 15}
{"x" : 25}
{"x" : [5, 25]}

如果想找出 “x” 的值在 10 和 20 之间的所有文档,那么你可能会本能地构建这样的查询,即 db.test.find({“x” : {“ g t " : 10 , " gt" : 10, " gt":10,"lt” : 20}}),然后期望它会返回一个文档:{“x” : 15}。然而,当实际运行时,我们得到了两个文档,如下所示:

> db.test.find({"x" : {"$gt" : 10, "$lt" : 20}})
{"x" : 15}
{"x" : [5, 25]}

5 和 25 都不在 10 和 20 之间,但由于 25 与查询条件中的第一个子句("x"的值大于 10)相匹配,5 与查询条件中的第二个子句(“x” 的值小于 20)相匹配,因此这个文档会被返回。
😐 这样就使得针对数组的范围查询基本失去了作用:一个范围会匹配任何多元素数组,有几种方法可以获得预期的行为
1.可以使用 e l e m M a t h 强制 M o n g o D B 将这两个子句与单个数组元素进行比较,不过 elemMath强制MongoDB将这两个子句与单个数组元素进行比较,不过 elemMath强制MongoDB将这两个子句与单个数组元素进行比较,不过elemMath不会匹配非数组元素

> db.test.find({"x" : {"$elemMatch" : {"$gt" : 10, "$lt" : 20}}})
> // 没有结果

文档 {“x” : 15} 不再与查询条件匹配了,因为它的 “x” 字段不是一个数组。也就是说,你应该有充分的理由在一个字段中混合数组和标量值,而这在很多场景中并不需要。对于这样的情况,“ e l e m M a t c h " 为数组元素的范围查询提供了一个很好的解决方案。 ∗ ∗ 2. 如果在要查询的字段上有索引(参见第 5 章),那么可以使用 m i n 和 m a x 将查询条件遍历的索引范围限制为 " elemMatch" 为数组元素的范围查询提供了一个很好的解决方案。 **2.如果在要查询的字段上有索引(参见第 5 章),那么可以使用 min 和 max 将查询条件遍历的索引范围限制为 " elemMatch"为数组元素的范围查询提供了一个很好的解决方案。2.如果在要查询的字段上有索引(参见第5章),那么可以使用minmax将查询条件遍历的索引范围限制为"gt” 和 “$lt” 的值**

> db.test.find({"x" : {"$gt" : 10, "$lt" : 20}}).min({"x" : 10}).max({"x" : 20})
{"x" : 15}

现在,这条查询语句只会遍历值在 10 和 20 之间的索引,不会与值为 5 和 25的这两个条目进行比较。但是,只有在要查询的字段上存在索引时,才能使用min 和 max,并且必须将索引的所有字段传递给 min 和 max
🍁在查询可能包含数组的文档的范围时,使用 min 和 max 通常是一个好主意。在整个索引范围内对数组使用 “ g t " / " gt"/" gt"/"lt” 进行查询是非常低效的。它基本上接受任何值,因此会搜索每个索引项,而不仅仅是索引范围内的值。

4.4 $where查询

概念: 允许你在查询中执行任意的 JavaScript 代码

例子:

> db.foo.find({"$where" : function () {
... for (var current in this) {
...     for (var other in this) {
...         if (current != other && this[current] == this[other]) {
...             return true;
...         }
...     }
... }
... return false;
... }});

注意:除非绝对必要,否则不应该使用 “$where” 查询:它们比常规查询慢得多

4.5 游标

概念:游标(Cursor)是用于遍历查询结果的对象,你执行查询时,MongoDB 返回一个游标,它指向查询结果的初始位置。通过游标,你可以逐步获取结果集中的文档,而不需要一次性将整个结果集加载到内存中。
案例:

> for(i=0; i<100; i++) {
...     db.collection.insertOne({x : i});
... }
> var cursor = db.collection.find();

> while (cursor.hasNext()) {
...     obj = cursor.next();
...     // 执行任务
... }

//还有一种用法,游标cursor类还实现了Js的迭代器接口,因此可以使用forEach
> var cursor = db.people.find();
> cursor.forEach(function(x) {
...     print(x.name);
... });
adam
matt
zak

上述案例中,find方法就返回一个游标,cursor.hasNext() 会检查是否有后续结果存在,而 cursor.next() 用来对其进行获取。
游标的工作机制:

  1. **查询请求:**当客户端发起一个查询请求,MongoDB服务器接受请求
  2. 返回游标:服务器会返回一个包含初始查询结果的游标给客户端,这是,并不会立刻返回所有匹配的文档,而是返回一个包含部分结果的游标对象,这个部分结果一般来说是100个结果或者4MB的数据(两者中较小者)
  3. 分批获取:客户端可以使用游标的方法(如next)来逐批获取文档。当客户端请求下一批文档时,服务器会在需要时继续执行查询,获取更多的文档,并返回给客户端。
  4. **游标生命周期:**获取的过程会一直持续,知道游标耗尽或者结果被全部返回

4.5.1 limit,skip和sort

  1. limit:会限制返回结果的数量,传入的参数只能是正数,负数会报错
  2. skip:会跳过指定数量的文档,然后返回剩下的文档,参数也是正数
  3. sort:会接受一个对象作为参数,这个对象是一组键–值对,键对应文档的键名,值对应排序的方向。排序方向可以是 1(升序)或 -1(降序)。如果指定了多个键,则结果会按照这些键被指定的顺序进行排序。例如,要按照 “username” 升序及 “age” 降序排列

案例:实现分页,假设你正在运营一个在线商店,有人想搜索 mp3。如果想每页返回 50 个结果并按照价格从高到低排序

> db.stock.find({"desc" : "mp3"}).limit(50).sort({"price" : -1})

//如果顾客单机下一页
> db.stock.find({"desc" : "mp3"}).limit(50).skip(50).sort({"price" : -1})

然而,略过大量的结果会导致性能问题
比较顺序
MongoDB 对于类型的比较有一个层次结构。有时一个键的值可能有多种类型:整型和布尔型,或者字符串和 null。如果对混合类型的键进行排序,那么会有一个预定义的排序顺序。从最小值到最大值,顺序如下。

  • 最小值
  • null
  • 数字(整型、长整型、双精度浮点型、小数型)
  • 字符串
  • 对象/文档
  • 数组
  • 二进制数据
  • 对象 ID
  • 布尔型
  • 日期
  • 时间戳
  • 正则表达式
  • 最大值

4.5.2 避免略过大量结果

使用 skip 来略过少量的文档是可以的。但对于结果非常多的情况,skip 会非常慢,因为需要先找到被略过的结果,然后再丢弃这些数据。大多数数据库会在索引中保存更多的元数据以处理 skip,但 MongoDB 目前还不支持这样做,所以应该避免略过大量的数据
1.不使用skip对结果进行分页
最简单的方式就是使用limit和skip互相配合,用偏移量来进行返回:

> // 不要这么做:略过大量数据会非常慢
> var page1 = db.foo.find(criteria).limit(100)
> var page2 = db.foo.find(criteria).skip(100).limit(100)
> var page3 = db.foo.find(criteria).skip(200).limit(100)
...

使用skip查询很多结果时,会非常慢,所以我们有一种不使用skip来进行分页的方法,就是使用排序和条件查询
假设要按照date**降序显式文档,**可以使用以下方式获取第一页:

> var page1 = db.foo.find().sort({"date" : -1}).limit(100)

然后,假设日期是唯一的,可以使用最后一个文档的 “date” 值作为获取下一页的查询条件:

var latest = null;

// 显示第1页
while (page1.hasNext()) {
    latest = page1.next();
    display(latest);
}

// 获取下一页
var page2 = db.foo.find({"date" : {"$lt" : latest.date}});
page2.sort({"date" : -1}).limit(100);

2.查询一个随机文档
我们首先也会翻译使用skip来随机跳过数据来获取

> // 不要这样做
> var total = db.foo.count()
> var random = Math.floor(Math.random()*total)
> db.foo.find().skip(random).limit(1)

以这种方式获取随机元素实际上非常低效:必须先计算总数(如果使用查询条件,这会是一个昂贵的操作),并且略过大量的元素也会非常耗时
我们还有一种比较好的方法,不过需要提前计划,在文档中设置random键

> db.people.insertOne({"name" : "joe", "random" : Math.random()})
> db.people.insertOne({"name" : "john", "random" : Math.random()})
> db.people.insertOne({"name" : "jim", "random" : Math.random()})

这样,我们就可以使用正常的条件查询来查询,而不用使用skip

> var random = Math.random()
> result = db.people.findOne({"random" : {"$gt" : random}})

random 可能会大于集合中的任何 “random” 值,并且不会返回任何结果。可以简单地从另一个方向返回文档以避免这种情况:

> if (result == null) {
...     result = db.people.findOne({"random" : {"$lte" : random}})
... }

如果集合中没有任何文档,那么这种方式会返回 null,这也是合理的。

4.5.3 游标生命周期

在服务器,游标会占用内存和资源,所以我们需要释放游标,有以下几种情况会释放游标

  • 当游标遍历完结果之后,它会清除自身
  • 当游标超出客户端的作用域,驱动程序会向数据库发送一条特殊的消息,让数据库知道它可以“杀死”该游标
  • 用户没有遍历完所有结果而且游标仍在作用域内,如果 10 分钟没有被使用的话,数据库游标也将自动“销毁”。

有时候,我们需要一个游标维持很长时间,这种情况下,我们应该怎么办呢?
许多驱动程序实现了一个称为 immortal 的函数,或者类似的机制,它告诉数据库不要让游标超时。
如果关闭了游标超时,则必须遍历完所有结果或主动将其销毁以确保游标被关闭。否则,它会一直占用数据库的资源,直到服务器重新启动

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

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

相关文章

虾皮一键铺货软件:如何使用一键铺货软件在Shopee平台上上架商品

在如今竞争激烈的电商市场中&#xff0c;卖家们都希望能够快速上架商品&#xff0c;以节省时间和精力&#xff0c;并提高销售效率。而在Shopee&#xff08;虾皮&#xff09;平台上&#xff0c;一键铺货软件成为了许多卖家的首选工具。这些软件不仅可以帮助卖家快速将商品批量上…

java基于ssm的房源管理系统+vue论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

Linux:nginx设置网站https

http和https的区别 http: 80 https: 443 这种协议比http协议要安全&#xff0c;因为传输数据是经过加密的 HTTPS简介 HTTPS其实是有两部分组成&#xff1a;HTTP SSL / TLS&#xff0c;也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过…

【附源码】Java计算机毕业设计-图书管理系统

【附源码】Java计算机毕业设计-图书管理系统 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX…

模糊综合评价

第一步&#xff1a;确定评价指标集 确定评语集&#xff1a;如好&#xff0c;很好 第二步&#xff1a;求出模糊评价矩阵P 其中Pij表示方案X在第i个指标处于第j级评语等等隶属度 并且在此阶段需要确认各指标的权系数向量A 第三步&#xff1a;利用矩阵的模糊乘法得到综合评价…

Linux第9步_通过终端查看U盘文件

学习完“USB设置”后&#xff0c;我们学习通过终端来查看U盘文件。前面讲解过使用鼠标打开U盘&#xff0c;但是在实际使用中&#xff0c;更多的还是采用命令来实现对U盘的操作。 1、在桌面&#xff0c;右击鼠标&#xff0c;弹出下面的界面: 2、点击上图中的“打开终端”&#…

[redis] redis的安装,配置与简单操作

一、缓存的相关知识 1.1 缓存的概念 缓存是为了调节速度不一致的两个或多个不同的物质的速度&#xff0c;在中间对速度较慢的一方起到加速作用&#xff0c;比如CPU的一级、二级缓存是保存了CPU最近经常访问的数据&#xff0c;内存是保存CPU经常访问硬盘的数据&#xff0c;而且…

PyQT5+MySQL的学生信息管理系统【附源码,运行简单】

PyQT5MySQL的学生信息管理系统【附源码&#xff0c;运行简单】 总览 1、《学生成绩管理系统》1.1 方案设计说明书设计目标需求分析工具列表 2、详细设计2.1 登录2.2 程序主页面2.3 学生新增界面2.4 学生更改界面2.4 学生删除界面2.5 其他功能贴图 3、下载 总览 自己做的项目&a…

YOLOv5改进 | 2023注意力篇 | MSDA多尺度空洞注意力(附多位置添加教程)

一、本文介绍 本文给大家带来的改进机制是MSDA(多尺度空洞注意力)发表于今年的中科院一区(算是国内计算机领域的最高期刊了),其全称是"DilateFormer: Multi-Scale Dilated Transformer for Visual Recognition"。MSDA的主要思想是通过线性投影得到特征图X的相应查…

windows下使用PowerShell切割大数据文件

测试文件为24.4G文件 打开PowerShell窗口&#xff0c;使用以下命令 $filePath 为指向文件路径 $outputPath 输出到指定文件夹 $chunkSize 单个文件控制切割大小 将命令修改完后&#xff0c;直接粘贴到powershell窗口&#xff0c;点击回车即可进行切割 $filePath "D:\…

ARM工控机Node-red使用教程

嵌入式ARM工控机Node-red安装教程 从前车马很慢书信很远&#xff0c;而现在人们不停探索“科技改变生活”。 智能终端的出现改变了我们的生活方式&#xff0c;钡铼技术嵌入式工控机协助您灵活布建能源管理、大楼自动化、工业自动化、电动车充电站等各种多元性IoT应用&#xff…

使用Docker-Compose部署MySQL一主二从同步高可用MHA集群

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容准备mysql一主二从同步集群一主二从同步集群规划需要安装docker和docker-compose命令形式安装安装docker安装docker-compose 宝塔面板形式安装 部署Master节点的docker-compose.yaml文件部署MySQL从节点1的docker-compose.…

XML技术分析01

一、什么是XML eXtensible Markup Language ——可扩展标记语言 1、标记&#xff08; markup &#xff09;及标记语言&#xff1a; markup的含义是指插入到文档(document)中的标记 标记&#xff1a;是以标志的格式附加在文档中的。标志赋予文档的某一部分一个标记的标识…

解决flask启动报错:ImportError: DLL load failed while importing _dukpy: 找不到指定的程序

现象&#xff1a; 原因&#xff1a;dukpy没有win32执行库 解决办法&#xff1a; 到lfd.uci.edu 第三方库下载dukpy的win32 whl文件 注意&#xff1a; 需要跟你python版本和windows平台&#xff08;32位/64位&#xff09;对应 https://www.lfd.uci.edu/~gohlke/pythonlibs/#…

科技感十足界面模板

科技感界面 在强调简洁的科技类产品相关设计中&#xff0c;背景多数分为&#xff1a;颜色或写实图片两种。 颜色很好理解&#xff0c;大多以深色底为主。强调一种神秘感和沉稳感&#xff0c;同时可以和浅色的文字内容形成很好的对比。 而图片背景的使用&#xff0c;就要求其…

小白入门基础 - Spring的Bean超详解

1.Spring工厂类的继承方式 从上面可以看出&#xff0c;创建工厂类&#xff0c;可以通过ClassPathXmlApplicationContext和FileSystemXmlApplicationContext这两种方式&#xff1a; FileSystemXmlApplicationContext从磁盘加载配置文件&#xff0c;此时就需要使用绝对路径。 pub…

2024跨境电商测评还能做吗?

基本上做跨境电商这块的都做过测评 原因也很简单&#xff0c;一方面review是产品转化率的重要保证&#xff0c;另一方面一个好的测评订单也可以有效的提升产品的关键词排名和点击率转化率 为什么说现在找测评是越来越难了呢 大环境因素是亚马逊卖家越来越多了&#xff0c;内…

ShardingSphere-JDBC学习笔记

引言 开源产品的小故事 Sharding-JDBC是2015年开源的&#xff0c;早期的定位就是一个分布式数据库的中间件&#xff0c;而在它之前有一个MyCat的产品。MyCat也是从阿里开源出来的&#xff0c;作为分库分表的代名词火了很长一段时间&#xff0c;而MyCat早年的目标就是想进入ap…

云计算:OpenStack 分布式架构管理VXLAN网络(单控制节点与多计算节点)

目录 一、实验 1.环境 2.各节点新增网卡准备VXLAN网络 3.控制节点配置私有网络 4.计算节点1配置私有网络 5.计算节点2配置私有网络 6.重启服务 7.修改Dashboard 8.新建项目&#xff08;租户&#xff09;及用户 9.新建网络与子网 10.新建实例 11.新建路由 12.新增浮…

使用PyTorch实现去噪扩散模型

在深入研究去噪扩散概率模型(DDPM)如何工作的细节之前&#xff0c;让我们先看看生成式人工智能的一些发展&#xff0c;也就是DDPM的一些基础研究。 VAE VAE 采用了编码器、概率潜在空间和解码器。在训练过程中&#xff0c;编码器预测每个图像的均值和方差。然后从高斯分布中对…