MongoDB之查询操作

1、查询所有

db.test.find()
db.test.find({})
2、根据键值对
db.test.find({“key”:value})
3、根据多个键查询,且关系为AND[且的关系]
db.test.find({“key”:value,”key1″:value1})
4、指定返回的键
db.test.find({},{“key”:value})
其中value为0代表不返回,value为1代表字段会返回
5、查询限制
传递给数据库的查询文档的值必须是常量。不能是变量,如以下实例即为错误的:
db.test.find({“key”:”this.key1″})

1、 比较运算符
“$lt”、”$lte”、”$gt” 和 “$gte” 都属于比较运算符,分别对应

1、null
假设test集合中没有age字段,相当于查询所有

db.test.find({“age”:null})
2、如果仅想匹配键值为 null 的文档,则需要检查该键的值是否为null,并且通过 “$exists” 条件确认该键已存在。
db.test.find({“name”:{“$eq”:null,”$exists”:true}})
3、正则表达式
“$regex” 可以在查询中为字符串的模式匹配提供正则表达式功能。
如果要查找所有用户名为 Zhang或 zhang 的用户,那么可以使用正则表达式进行不区分大小写的匹配:
db.test.find({“name”:{“$regex”:/zhang/i}})
希望匹配如”zhangs”这样的键,那么可以改进一下刚刚的正则表达式
db.test.find({“name”:{“$regex”:/zhangs?/i}})
注: MongoDB 可以利用索引来查询前缀正则表达式(如/^zhang/)。索引不能用于不区分大小写的搜索(/^zhangs/i)。当正则表达式以插入符号(^)或左锚点(\A)开头时,它就是”前缀表达式”。如果正则表达式使用了区分大小写的查询,那么当字段存在索引时,则可以对索引中的值进行匹配。如果它也是一个前缀表达式,那么可以将搜索限制在由该索引的前缀所形成的范围内的值。

正则表达式也可以匹配自身。虽然很少有人会将正则表达式插入数据库中,但是如果你这么做了,那么它也可以匹配到自身。

db.test.insert({“name”:/zhang/})
db.test.find({“name”:/zhang/})
4、数组查询
1)、匹配文档
db.test.insertOne({“address”:[“addr1″,”addr2″,”addr3”]})
db.test.find({“address”:”addr1″})
2)、同时包含,且跟顺序无关
db.test.find({“address”:{“$all”:[“addr1″,”addr2”]}})
3)、精确匹配且顺序必须一致
db.test.find({“address”:[“addr1″,”addr2″,”addr3”]})
4)、根据下标查询,数组下标都是从0开始
db.test.find({“address.2″:”addr2”})
5)、查询特定长度的数组
db.test.find({“address”:{“$size”:3}})
“$size” 并不能与另一个$ 条件运算符(如 “$gt”)组合使用,但这种查询可以通过在文档中添加一个 “size” 键的方式来实现。
db.test.update(query,{“$push”:{“$address”:”addr3″},{“$inc”:{“size”:1}}})
后续查询就可以通过size来查询,如:
db.test.find({“size”:{“$gt”:3}})
6)、”$slice” 运算符可以返回一个数组键中元素的子集。
如,返回前10条数据:
db.test.find(query,{“address”:{“$slice”:10}})
返回后10条记录:
db.test.find(query,{“address”:{“$slice”:-10}})
指定偏移量和返回的元素数量来获取数组中间的结果:
db.test.find(query,{“address”:{“$slice”:[23,10]}})
这个操作会略过前 23 个元素,返回第 24~33 个元素。如果数组中的元素少于 33 个,则会返回尽可能多的元素。
7)、返回与查询条件匹配的任意数组元素,使用 $运算符来返回匹配的元素
db.test.find({“name”:”zhangsan”},{“address.$”:1})
这种方式只会返回每个文档中第一个匹配的元素:如果zhangsan 在资料中留下了多地址,那么只有 “comments” 数组中的第一个会被返回。
8)、数组与范围查询的相互作用
比如目前有如下文档
{“x”:5}
{“x”:15}
{“x”:25}
{“x”:[5,25]}
db.test.find({“x”:{“$gt”:10,”$lt”:20}})
{“x”:15}
db.test.find({“x”:{“$gt”:10,”$”:25}})
{“x”:15}
{“x”:[5,25]}
5 和 25 都不在 10 和 20 之间,但由于 25 与查询条件中的第一个子句(”x” 的值大于 10)相匹配,5 与查询条件中的第二个子句(”x” 的值小于 20)相匹配,因此这个文档会被返回。
明显与预期结果不一致,所以可以使用 “$elemMatch” 强制 MongoDB 将这两个子句与单个数组元素进行比较。不过,这里有一个问题,”$elemMatch” 不会匹配非数组元素:
db.test.find({“x”:{“$elemMatch”:{“$gt”:10,”$lt”:20}}})
此时是没有结果返回的
9)、如果在要查询的字段上有索引,那么可以使用min 和 max 将查询条件遍历的索引范围限制为 “$gt” 和 “$lt”的值:
db.test.find({“x”:{“$gt”:10,”$lt”:20}}).min({“x”:10}).max({“x”:20})
现在,这条查询语句只会遍历值在 10 和 20 之间的索引,不会与值为 5 和 25 的这两个条目进行比较。但是,只有在要查询的字段上存在索引时,才能使用 min 和 max,并且必须将索引的所有字段传递给 min 和 max。
在查询可能包含数组的文档的范围时,使用 min 和 max 通常是一个好主意。在整个索引范围内对数组使用 “$gt”/”$lt” 进行查询是非常低效的。它基本上接受任何值,因此会搜索每个索引项,而不仅仅是索引范围内的值。
5、查询内嵌文档
查询姓名为zhang san的人,精确匹配
db.test.find(“name”:{“first”:”zhang”,”last”:”san”})
针对特定的键进行查询
db.test.find({“name.first”:”zhang”})
这种点表示法是查询文档和其他文档类型的主要区别。查询文档可以包含点,表示”进入内嵌文档内部”的意思。点表示法也是待插入文档不能包含 . 字符的原因。当试图将 URL 保存为键时,常常会遇到这种限制。解决这个问题的一种方法是在插入前或者提取后始终执行全局替换,用点字符替换 URL 中不合法的字符。
6、内嵌文档中的数组查询
userInfos是一个数组,包含多个userinfo
db.test.find({“userinfos”:{“$elemMatch”:{“name”:”zhangsan”,”age”:{“$gte”:6}}}})
要正确指定一组条件而无须指定每个键,请使用”$elemMatch”,”$elemMatch” 允许你将限定条件进行”分组”。仅当需要对一个内嵌文档的多个键进行操作时才会用到它。

键–值对是一种相当有表现力的查询方式,但有些查询依然无法表示。对于无法以其他方式执行的查询,可以使用 “$where” 子句,它允许你在查询中执行任意的 JavaScript 代码。这样就能在查询中做大部分事情了。为安全起见,应该严格限制或消除”$where” 子句的使用。应该禁止终端用户随意使用 “$where”子句。
使用 “$where” 最常见的情况是比较文档中两个键的值。假设有如下文档:

db.test.insertOne({“name”:”zhangsan”,”age”:10})
db.test.insertOne({“name”:”lisi”,”age”:20,”height”:20})
返回任意两个字段相等的文档
db.test.find({“$where”:function(){
for(var current in this){
for(var other in this){
if(current!=other&&this[current]==this[other]){
return true;
}
}
}
return false;
}})
如果函数返回 true,文档就作为结果集的一部分返回;如果函数返回 false,文档就不返回。
除非绝对必要,否则不应该使用 “$where” 查询:它们比常规查询慢得多。每个文档都必须从 BSON 转换为 JavaScript 对象,然后通过 “$where” 表达式运行。此外,”$where” 也无法使用索引。因此,只有在没有使用其他方法进行查询时,才可以使用 “$where”。可以先使用其他查询进行过滤,然后再使用”$where” 子句,这样组合使用可以降低性能损失。如果可能,应该使用索引来基于非 $where 子句进行过滤,而 “$where”表达式仅用于对结果进行进一步微调。MongoDB 3.6 增加了$expr 运算符,它允许在 MongoDB 查询语句中使用聚合表达式。因为它不需要执行 JavaScript,所以速度比 $where 快,建议尽可能使用此运算符作为替代。
进行复杂查询的另一种方法是使用聚合工具.

1、数据库会使用游标返回 find 的执行结果。游标的客户端实现通常能够在很大程度上对查询的最终输出进行控制。你可以限制结果的数量,跳过一些结果,按任意方向的任意键组合对结果进行排序,以及执行许多其他功能强大的操作。

var cursor = db.test.find();
while(cursor.hasNext()){
obj = cursor.next();
//执行业务逻辑
}
还可以迭代游标
cursor.forEach(function(x){
print(x.name);
})
调用 find 时,shell 并不会立即查询数据库,而是等到真正开始请求结果时才发送查询,这样可以在执行之前给查询附加额外的选项。cursor 对象的大多数方法会返回游标本身,这样就可以按照任意顺序将选项链接起来了。
var cursor = db.test.find();只是构造查询,查询还没有真正执行,cursor.hasNext()调用时才会执行,这时,查询会被发往服务器端。shell 会立刻获取前 100 个结果或者前 4MB 的数据(两者之中较小者),这样下次调用 next或者 hasNext 时就不必再次连接服务器端去获取结果了。在客户端遍历完第一组结果后,shell 会再次连接数据库,使用getMore 请求更多的结果。getMore 请求包含一个游标的标识符,它会向数据库询问是否还有更多的结果,如果有则返回下一批结果。这个过程会一直持续,直到游标耗尽或者结果被全部返回。
2、limit、skip和sort
只返回 3 个结果
db.test.find().limit(3)
略过前 3 个匹配的文档
db.test.find().skip(3)
sort排序方向可以是 1(升序)或 -1(降序)
db.test.find().sort({“name”:1,”age”:-1})
3、比较顺序
MongoDB 对于类型的比较有一个层次结构。有时一个键的值可能有多种类型:整型和布尔型,或者字符串和 null。如果对混合类型的键进行排序,那么会有一个预定义的排序顺序。从最小值到最大值,顺序如下。
最小值
null
数字(整型、长整型、双精度浮点型、小数型)
字符串
对象/文档
数组
二进制数据
对象 ID
布尔型
日期
时间戳
正则表达式
最大值
4、避免略过大量结果
使用 skip 来略过少量的文档是可以的。但对于结果非常多的情况,skip 会非常慢,因为需要先找到被略过的结果,然后再丢弃这些数据。大多数数据库会在索引中保存更多的元数据以处理 skip,但 MongoDB 目前还不支持这样做,所以应该避免略过大量的数据。通常下一次查询的条件可以基于上一次查询的结果计算出来。
不使用skip对结果进行分页
var page=db.test.find().sort({“date”:-1}).limit(100)
然后,假设日期是唯一的,可以使用最后一个文档的 “date” 值作为获取下一页的查询条件:
var latest = null;
//显示第一页
while(page.hasNext()){
latest = page.next();
display(latest);
}
//获取第二页
var page2 = db.test.find({“date”:{“$lt”:latest.date}})
page2.sort({“date”:-1}).limit(100)
5、查找一个随机文档
如果是以下方式,有可能会略过很多文档,性能不佳
db.test.find().skip(random).limit(1)
所以需要一些提前规划,但如果你知道要在集合中查找随机元素,那么有一种高效得多的方法可以执行此操作。诀窍就是在插入文档时为每个文档添加一个额外的随机键。如果正在使用shell,那么可以使用 Math.random() 函数(这会产生 0 和 1 之间的一个随机数):
random=Math.random();
db.test.insertOne({“name”:”zhang”,”random”:Math.random()})
db.test.find({“random”:{“$gt”:random}})
6、游标生命周期
游标包括两个部分:面向客户端的游标和由客户端游标所表示的数据库游标。我们用的基本都是客户端游标:
1)、在服务器端,游标会占用内存和资源。一旦游标遍历完结果之后,或者客户端发送一条消息要求终止,数据库就可以释放它正在使用的资源。释放这些资源可以让数据库将其用于其他用途,这是非常有益的,因此要确保可以尽快(在合理的范围内)释放游标。
2)、还有一些情况可能导致游标终止以及随后的清理。首先,当游标遍历完匹配的结果时,它会清除自身。其次,当游标超出客户端的作用域时,驱动程序会向数据库发送一条特殊的消息,让数据库知道它可以”杀死”该游标。最后,即使用户没有遍历完所有结果而且游标仍在作用域内,如果 10 分钟没有被使用的话,数据库游标也将自动”销毁”。这样,如果客户端崩溃或者出错,MongoDB 就不需要维护上千个被打开的游标了。
3)、这种”超时销毁”的机制通常是用户所期望的:很少有用户愿意花几分钟坐在那里等待结果。然而,有时可能的确需要一个游标维持很长时间。在这种情况下,许多驱动程序实现了一个称为 immortal 的函数,或者类似的机制,它告诉数据库不要让游标超时。如果关闭了游标超时,则必须遍历完所有结果或主动将其销毁以确保游标被关闭。否则,它会一直占用数据库的资源,直到服务器重新启动。

Original: https://blog.csdn.net/ntzzzsj/article/details/125333146
Author: 逆天至尊
Title: MongoDB之查询操作

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/795047/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 动手学数据分析 | 函数大杂烩

    在这里我主要复习一下用到的函数 本次课程的总任务是实战kaggle上泰坦尼克号的任务,对其数据集进行分析, 主要利用pandas实现。 第一章 :数据载入及初步观察 导入numpy…

    Python 2023年8月8日
    068
  • Django 开发教程

    Django 开发教程 创建项目 在命令行中创建一个新项目,使用 startproject 命令: $ django-admin startproject mysite 其中 my…

    Python 2023年8月4日
    062
  • python绘制分布曲线

    抵扣说明: 1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。 Original: https://blo…

    Python 2023年8月20日
    052
  • Linux安装Anaconda教程

    1. 首先上Linux官网下载最新 对应版本 的Anaconda安装包 链接: Anaconda官网下载 2. 因为我们是在Linux系统下安装Anaconda,所以选择Linux…

    Python 2023年8月1日
    063
  • C语言函数详解

    一、函数的定义与分类 1.定义 2.分类 二、库函数 1.库函数存在的意义 2.库函数的学习和使用 三、自定义函数 1.自定义函数的组成 2.示例 (1)写一个函数找出两个整数的最…

    Python 2023年9月16日
    044
  • pandas——Dataframe的多种创建方式

    理解Dataframe Dataframe是pandas中的一种数据结构,表示二维矩阵的数据表,区别于列表和字典这种一维的结构。二维具体表示为行和列,类似于sql中表的格式(或者简…

    Python 2023年8月22日
    071
  • 我的Pandas

    读取.csv文件 data=pd.read_csv(r’name.csv’,encoding=’utf-8′) pandas (inplace = True) 这个东西呢 data…

    Python 2023年8月16日
    044
  • 如何释放dataframe使用的内存

    我在熊猫中打开了一个非常大的csv文件,如下所示。 import pandas df = pandas.read_csv(‘large_txt_file.txt’) 完成此操作后,…

    Python 2023年8月23日
    090
  • 为什么感觉现在很少有黑客了?

    有一个词语,人人不是它,却人人都提及它,他就是:黑客! 黑客,这个我们从小就接触的工种,总是衣服全身黑衣、眼戴墨镜、冷酷无情、超级厉害的形象,关键是,只要应用崩了/数据丢了等各种突…

    Python 2023年9月16日
    049
  • Python中的函数

    目录 ​​Python内置函数​​ ​​函数式编程​​ ​​匿名函数(lambda)​​ ​​函数作为参数 ​​ ​​返回函数(闭包)​​ ​​装饰器​​ ​​Python中内置的…

    Python 2023年5月25日
    091
  • 【seaborn】(1) 数据可视化,绘图风格、布局

    各位同学好,今天和大家分享一下如何使用 seaborn 库进行数据可视化。在 matplotlib 的基础上进一步美化绘图。主要内容有: 默认风格 sns.set(), 主题风格 …

    Python 2023年8月31日
    074
  • 《Tango With Django2》Chapter5笔记 — Model & DB

    Django用对象关系映射器(Object Relational Mapper, ORM)¹来访问存储在数据库中的数据 本质上,存储在数据库表中的数据是通过Django模型封装的。…

    Python 2023年8月6日
    062
  • Shell系统学习之Shell变量和引用

    系列文章目录 变量的类型 变量的定义 变量的作用域 系统变量 环境变量 变量的赋值与清空 引用变量的值 引用和替换 变量的类型 Shell是 动态类型语言和 弱类型语言。 动态类型…

    Python 2023年11月8日
    032
  • Matplotlib 在图表中嵌入图片 — `imshow` 的各种用法解析

    Matplotlib 是一个用于绘制图表的 Python 标准库,可以用来完成可视化、数据分析、动画制作、科研制图等任务。本文介绍如何在 Matplotlib 的图表中嵌入图片。M…

    Python 2023年8月31日
    088
  • SSH端口转发

    SSH Port Forwarding 什么是SSH端口转发? SSH端口转发也被称为SSH隧道,我们知道SSH是加密通讯的,所以通过SSH建立的隧道传输的内容是安全的。它通常被用…

    Python 2023年10月13日
    041
  • springcloud3 EurekaClient集群的搭建2

    一 概述 1.1 概述 本文主要是搭建集成eurekaserver的几个客户端,即服务提供者,消费者。架构图如下所示 1.2 使用eureka整合的优点 使用Eureka管理注册的…

    Python 2023年9月26日
    040
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球