MongoDB学习笔记三:查询

MongoDB中使用find来进行查询。查询就是返回一个集合中文档的子集,子集合的范围从0个文档到整个集合。find的第一个参数决定了要返回哪些文档,其形式也是一个文档,说明要执行的查询细节。
空的查询文档{}会匹配集合的全部内容。要是不指定查询文档,默认就是{}。
例如:
> db.c.find()
将返回集合c中的所有内容。
查找所有"age"的值为27的文档:
> db.users.find({"age" : 27})
查找所有值为"joe"的"username"键:
> db.users.find({"username" : "joe"})
可以通过向查询文档加入多个键/值对的方式来将多个查询条件组合在一起。例如,查询所有用户名为"joe"且年龄为27岁的用户:
> db.users.find({"username" : "joe", "age" : 27})
『指定返回的键』
有时并不需要将文档中的所有键/值对都返回。遇到这种情况,可以通过find(或者findOne)的第二个参数来指定想要的键。
例如,如果只对用户集合的"username"和"email"键感兴趣,可以使用如下查询返回这些键:
> db.users.find({}, {"username" : 1, "email" : 1})
也可以用第二个参数来剔除查询结果中的某个键/值对。例如,文档中有很多键,但是不希望结果中含有"fatal_weakness"键:
> db.users.find({}, {"fatal_weakness" : 0})
也可以用来防止返回"_id":
> db.users.find({}, {"username" : 1, "_id" : 0})
查询条件
比较操作符"$lt"、"$lte"、"$gt"、"$gte"分别对应<、<=、>、>=。
例:查询在18~30岁(含)的用户:
> db.users.find({"age" : {"$gte" : 18, "$lte" : 30}})
查询在2007年1月1日前注册的人:
> start = new Date("01/01/2007")
> db.users.find({"registered" : {"$lt" : start}})
使用条件操作符"$ne"表示"不相等"。
例:查询所有名字不为"joe"的用户:
> db.users.find({"username" : {"$ne" : "joe"}})
"$ne"能用于所有类型的数据。
『OR查询』
MongoDB中有两种方式进行OR查询:"$in"用来查询一个键的多个值;"$or"用来完成多个键值的任意给定值。
对于单一键要是有多个值与其匹配的话,就要用"$in"加一个条件数组。例如,抽奖活动的中奖号码是725、542和390.要找出全部这些中奖数据,可以构建如下查询:
> db.raffle.find({"ticket_no" : {"$in" : [725, 542, 390]}})
"$in"可以指定不同的类型的条件和值。例如,在逐步将用户名的ID号迁移成用户名的过程中,要做兼顾二者的查询:
> db.users.find({"user_id" : {"$in" : [12345, "joe"]}})
这会匹配"user_id"等于12345的文档,也会匹配"user_id"等于"joe"的文档。
如果"$in"对应的数组只有一个值,那么和直接匹配这个值效果是一样的。例如,{ticket_no : {$in : [725]}}等价于{ticket_no : {$in : 725}}。
与"$in"相对的是"$nin",将返回与数组中所有条件都不匹配的文档。要是想返回所有没有中奖的人,就可以用如下方法进行查询:
> db.raffle.find({"ticket_no" : {"$nin" : [725, 542, 390]}})
查询将会返回没有那些号码的人。
"$or"接受一个包含所有可能条件的数组作为参数。例:找"ticket_no"为725或者"winner"为true的文档:
> db.raffle.find({"$or" : [{"ticket_no" : 725}, {"winner" : true}]})
"$or"可以含有其他条件句。例如,如果想要将"ticket_no"与那三个值匹配上,外加"winner"键,就可以这么做:
> db.raffle.find({"$or" : [{"ticket_no" : {"$in" : [725, 542, 390]}}, {"winner" : true}]})
『$not』
"$not"是元条件句,即可以用在任何其他条件之上。例:对于取模运算符"$mod"来说。"$mod"会将查询得知除以第一个给定值,若余数等于第二个给定值则返回该结果:
> db.users.find({"id_num" : {"$mod" : [5, 1]}})
上面的结果会返回"id_num"值为1、6/11/16等的用户。如果要返回"id_num"为2、3、4、5、7、8、9、10、12等的用户,则应使用"$not":
> db.users.find("id_num" : {"$not" : {"$mod" : [5, 1]}})
!"$not"与正则表达式联合使用的时候极为有用,用来查找那些与特定模式不符的文档。
『条件句的规则』
条件句是内层文档的键,而修改器则是外层文档的键。
一个键可以由多个条件,但是一个键不能对应多个更新修改器。
『特定于类型的查询』
"null"不仅能匹配自身,而且能匹配"不存在的"。
如果仅仅想要匹配键值为null的文档,既要检查该键的值是否为null,还要通过"$exists"条件判定值已经已存在:
> db.c.find({"z" : {"$in" : [null], "$exists" : true}})
『正则表达式』
例:想要查找所有名为Joe或者joe的用户,就可以使用正则表达式执行忽略大小写的匹配:
> db.users.find({"name" : /joe/i})
匹配各种大小写的joe以及joey:
> db.users.find({"name" : /joe?/i})
MongoDB使用Perl兼容的正则表达式(PCRE)库来匹配正则表达式,PCRE支持的正则表达式语法都能被MongoDB所接受。
MongoDB可以为前缀正则表达式(比如/^joey/)查询创建索引,所以这种类型的查询会非常高效。
正则表达式也可以匹配自身。虽然几乎没有人直接将正则表达式插入到数据库中,但是万一这么做了,也是可以用自身匹配的:
> db.foo.insert({"bar" : /baz/})
> db.foo.find({"bar" : /baz/})
查询数组
数组绝大多数情况下可以这样理解:每一个元素都是整个键的值。例如,如果数组是一个水果清单,比如下面这样:
> db.food.insert({"fruit" : ["apple", "banana", "peach"]})
下面的查询:
> db.food.find({"fruit" : "banana"})
会成功匹配该文档。
①$all
通过多个元素来匹配数组,使用"$all"。
例如,假设创建包含3个元素的如下集合:
> db.food.insert({"_id" : 1, "fruit" : ["apple", "banana", "peach"]})
> db.food.insert({"_id" : 2, "fruit" : ["apple", "kumquat", "orange"]})
> db.food.insert({"_id" : 3, "fruit" : ["cherry", "banana", "apple"]})
要找到既有"apple"又有"banana"的文档,就得用"$all"来查询:
> db.food.find(fruit : {$all : ["apple", "banana"]})
db.food.insert({"_id" : 1, "fruit" : ["apple", "banana", "peach"]})
db.food.insert({"_id" : 3, "fruit" : ["cherry", "banana", "apple"]})
要是想查询数组指定位置的元素,则需使用key.index语法指定下标,如:
> db.food.find({"fruit.2" : "peach"})
数组下标从0开始,上面的表达式会用数组的第3个元素和"peach"匹配。
②$size
"$size"用于查询指定长度的数组。例:
> db.food.find({"fruit" : {"$size" : 3}})
③$slice操作符
find的第二个参数是可选的,可以指定返回那些键。"$slice"返回数组的一个子集合。
例如,假设现在有一个博客文章的文档,要想反悔前10条评论,可以:
> db.blog.posts.findOne(criteria, {"comments" : {"$slice" : 10}})
也可以返回后10条评论,只要-10就可以了:
> db.blog.posts.findOne(criteria, {"comments" : {"$slice" : -10}})
"$slice"也可以接受偏移值和要返回的元素数量,来返回中间的结果:
> db.blog.posts.findOne(criteria, {"comments" : {"$slice" : [23, 10]}})
这个操作会跳过前23个元素,返回第24个~第33个元素。如果数组不够33个元素,则返回第23个元素后面的所有元素。
使用"$slice"默认返回文档中的所有键。
『查询内嵌文档』
有两种方法查询内嵌文档:查询整个文档,或者只针对键/值对进行查询。
例,对于如下文档:
{
"name" : {
"first" : "Joe"
"last" : "Schmoe"
},
"age" : 45
}
要查询姓名为Joe Schmoe的人可以这样:
> db.people.find({"name" : {"first" : "Joe", "last" : "Schmoe"}})
可以使用点表示法查询内嵌的键:
> db.people.find({"name.first" : {"first" : "Joe", "last" : "Schmoe"}})
例:假设有博客文章若干,要找到由Joe发表的5分以上的评论。要正确地指定一组条件,而不用指定每个键,要使用"$elemMatch"。这种模糊的命名条件句能用来部分指定匹配数组中的单个内嵌文档的限定条件:
> db.blog.find({"comments" : {"$elemMatch" : {"author" : "joe", "score" : {"$gte" : 5}}}})
"$elemMatch"将限定条件进行分组,仅当需要对一个内嵌文档的多个键操作时才会用到。
『$where查询』
使用"$where"可以执行任意JavaScript作为查询的一部分。
最典型的应用就是比较文档中的两个键的值是否相等。例如,有个条目列表,如果其中的两个值相等则返回文档。如下示例:
> db.foo.insert({"apple" : 1, "banana" : 6, "peach" : 3})
> db.foo.insert({"apple" : 8, "spinach" : 4, "watermelon" : 4})
第二个文档中,"spinach"和"watermelon"的值相同,所以需要返回该文档。MongoDB似乎用于不会提供一个$条件符来做这个,所以只能用"$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;
}});
如果函数返回true,文档就作为结果的一部分被返回;如果为false,则不然。
也可以用一个字符串来指定"$where"查询。下面两种表达式是完全等价的:
> db.foo.find({"$where" : "this.x + this.y == 10"})
> db.foo.find({"$where" : "function() { return this.x + this.y == 10; }"})
"$where"在速度上比常规查询慢很多。
『游标』
要想从shell中创建一个游标,首先要对集合填充一些文档,然后对其执行查询,并将结果分配给一个局部变量(用var生命的变量就是局部变量)。这里,先创建一个简单的几何,而后做个查询,并用cursor变量保存结果:
> for(i=0; i<100; i++) {
db.collection.insert({x : i});
}
> var cursor = db.collection.find();
要跌待结果,可以使用游标的next方法。也可以使用hasNext来查看有没有其他结果。典型的结果遍历如下:
> while (cursor.hasNext()) {
obj = cursor.next();
// do stuff
}
cursor.hasNext()检查是否有后续结果存在,然后用cursor.next()将其获得。
游标类还实现了迭代器接口,可以在foreach循环中使用。
> var cursor = db.people.find()
> cursor.forEach(function(x) {
print(x.name);
});
『limit、skip和sort』
要限制结果数量,可在find后使用limit函数。例如,只返回3个结果,可以这样:
> db.c.find().limit(3)
忽略掉前3个匹配的文档,然后返回余下的文档:
> db.c.find().skip(3)
sort用一个对象作为参数:一组键/值对,键对应文档的别名,值代表排序的方向。排序方向可以是1(升序)或者-1(降序)。如果指定了多个键,则按照多个键的顺序逐个排序。例如,要按照"username"升序及"age"降序排序,可以这样写:
> db.c.find().sort({username : 1, age : -1})
这3个方法可以组合使用。这对于分页非常有用。例如,你有个在线商店,有人想搜索mp3。若是想每页返回50个结果,而且按照价格从高到低排序,可以这样写:
> db.stock.find({"desc" : "mp3"}).limit(50).sort({"price" : -1})
点击“下一页”可以看到更多的结果,通过skip也可以非常简单地实现,只需要略过前50个结果就好了(已经在第一页显示了):
> db.stock.find({"desc" : "mp3"}).limit(50).skip(50).sort({"price" : -1})
比较顺序:MongoDB处理不同类型的数据有一个顺序:
(1)最小值
(2)null
(3)数字(整型、长整型、双精度)
(4)字符串
(5)对象/文档
(6)数组
(7)二进制数据
(8)对象ID
(9)布尔型
(10)日期型
(11)时间戳
(12)正则表达式
(13)最大值
『避免使用skip略过大量结果』
1.不用skip的结果进行分页
最简单的分页方法是用limit返回结果的第一页,然后将每个后续页面作为相对于开始的偏移量返回。
> // do not use: slow for large skips
> var page1 = db.foo.find(criteria).limit(100)
> var page2 = db.foo.find(criteris).skip(100).limit(100)
> var page3 = db.foo.find(criteris).skip(200).limit(100)
...
然而,一般来讲可以找到一种方法实现不用skip的分页,这取决于查询本身。例如,要按照"date"降序显示文档,可以用如下方式获取结果的第一页:
> var page1 = db.foo.find().sort({"date" : -1}).limit(100)
然后,可以利用最后一个文档中"date"的值作为查询条件,来获取下一页:
var latest = null;

// dispaly first page
while (page1.hasNext()) {
latest = page1.next();
display(latest);
}

// get next page
vat page2 = db.foo.find({"date" : {"$gt" : latest.date}});
page2.sort({"date" : -1}).limit(100);
这样查询中就没有skip了。
2.随机选取文档
例:想随机找一个加州的水暖工,可以对"profession"、"state"和"random"建立索引:
> db.people.ensureIndex({"profession" : 1, "state" : 1, "random" : 1})
这样就能很快得出一个结果了。
『高级查询选项』
查询分为包装的和普通的两类。
普通的查询:
> var cursor = db.foo.find({"foo" : "bar"})
有几个选项用于包装查询。例如,假设我们执行一个排序:
> var cursor = db.foo.find({"foo" : "bar"}).sort({"x" : 1})
实际情况不是将{"foo" : "bar"}作为查询直接发送给数据库,而是将查询包装在一个更大的文档中。shell会把查询从{"foo" : "bar"}转换成{"$query" : {"foo" : "bar"}}, "$orderby" : {"x" : 1}
绝大多数驱动程序有些辅助措施向查询添加各种选项。举例:
· $maxscan : integer
指定查询最多扫描的文档数量
· $min : document
查询的开始条件
· $max : document
查询的结束条件
· $hint : document
指定服务器使用哪个索引进行查询
· $explain : boolean
获取查询执行的细节(用到的索引、结果数量、耗时等),而并非真正执行查询。
· $snapshot : boolean
确保查询的结果是在查询执行那一刻的一致快照
获取一致结果:当使用了"$snapshot"选项,查询就是针对不变的集合视图运行的。
游标内幕:客户端游标以及客户端游标表示的数据库游标。

 

转载于:https://www.cnblogs.com/answernotfound/p/mongodbnote3.html

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

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

相关文章

计算机基础 课程简介,课程简介及计算机基础知识课件.ppt

文档介绍&#xff1a;C语言程序设计主讲教师:王伟****************qtc.课程简介:课程类别:专业计划学时:644学时/周16周课程学分:4课程学****结束后要求达到的要求掌握C语言的基础知识能在TurboC和VC的环境中设计程序实现解决小规模问题上课要求:不迟到、不早退,有事和身体原因…

困扰程序员的30种软件开发问题,你是否时曾相识?

我相信许多web开发人员和软件工程师在编程中都会遇到困难&#xff0c;而事后回想起来&#xff0c;还会觉得很好笑。1、我不知道该删掉还是重写回归曾经写的源代码&#xff0c;总有一种想要重新返工的冲动&#xff0c;逻辑性差&#xff0c;冗余代码多&#xff0c;让人难以理解。…

SQl 作业方面(转)

企业管理器 --管理 --SQL Server代理 --右键作业 --新建作业 --"常规"项中输入作业名称 --"步骤"项 --新建 --"步骤名"中输入步骤名 --"类型"中选择"Transact-SQL 脚本(TSQL)" --"数据库"选择执行命令的数据库 --…

燕山大学计算机专业研究生怎么样,求助大家!重庆邮电大学计算机专业的研究生值得一读吗?...

求助大家&#xff01;重庆邮电大学计算机专业的研究生值得一读吗&#xff1f; 魅力前线 yanshandaxue2008-4-22 1 / 13 aiyabukaoyan2008-4-22 16:28求助大家&#xff01;重庆邮电大学计算机专业的研究生值得一读吗&#xff1f; 云南大学 yanshandaxue2008-4-22 1 / 13 每天一点…

有哪些新手程序员不知道的小技巧?

1.重构是程序员的主力技能。2.工作日志能提升脑容量。3.先用profiler调查&#xff0c;才有脸谈优化。4.注释贵精不贵多。杜绝大姨妈般的“例注”。漫山遍野的碎碎念注释&#xff0c;实际就是背景噪音。5.普通程序员google超级程序员。6.单元测试总是合算的。7.不要先写框架再写…

Bezier曲线

1. 学习网址 http://give.zju.edu.cn/cgcourse/new/book/8.2.htm转载于:https://www.cnblogs.com/icmzn/p/5082154.html

绝地求生登录计算机需要授权,绝地求生国服第三方授权登录异常解决方法 绝地求生国服授权登录错误怎么办...

近日&#xff0c;Steam第三方授权登录发生异常&#xff0c;导致所有需要Steam账号绑定登录的网站都出现登录错误&#xff0c;下面就为大家带来绝地求生国服第三方授权登录异常解决方法。绝地求生国服第三方授权登录异常解决方法老兵登机活动绑定公告亲爱的老兵们&#xff1a;今…

USE平台构件属性无法显示的一种解决办法

国开行USE平台&#xff0c;构件属性无法完整显示&#xff0c;是因为ADSafe&#xff08;净网大师&#xff09;的拦截。关闭掉净网大师就OK了。转载于:https://www.cnblogs.com/helloIT/articles/5082188.html

SQL Server索引怎么用

什么是索引拿汉语字典的目录页&#xff08;索引&#xff09;打比方&#xff1a;正如汉语字典中的汉字按页存放一样&#xff0c;SQL Server中的数据记录也是按页存放的&#xff0c;每页容量一般为4K 。为了加快查找的速度&#xff0c;汉语字&#xff08;词&#xff09;典一般都有…

EF 实现自定义数据库字符串

1、EF模板生成继承DbContext的类文件重新建一个部分类文件避免每次生成实体都会覆盖掉。2、重新构造调用数据库连接字符串的函数VS模板生成示例&#xff1a;public Test_DBEntities(): base("nameTest_DBEntities"){} 重写函数public Test_DBEntities(string conn…

函数及自定义函数

SQL Server中的函数&#xff08;字符串函数&#xff0c;日期函数&#xff0c;数学函数&#xff0c;系统函数&#xff09; 字符串函数&#xff08;用于控制返回给用户的字符串&#xff09; 1.charindex 寻找一个指定的字符串在另一个字符串中的起始位置 select charindex (JB…

链表定义、链表的插入、链表的删除、链表的查找

链表的定义 链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个“头指针”变量&#xff0c;以head表示&#xff0c;它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”&#xff0c;每个结点都应包括两…

原神服务器维护后抽奖池会更新吗,原神:武器池改动,玩家的诉求再次得到反馈!PS端将与官服互通!...

大伙直播都看了吗&#xff1f;反正我看完了。现在满脑子都是大伟哥的嗯典。这好吗&#xff1f;这不好。但是没有关系&#xff0c;内容还是有的。首先&#xff0c;剧情上的雷神确立了&#xff0c;就是这位大姐。(好像有什么锋利的东西悬在了我的头顶&#xff0c;不过这上面&…

EF性能优化(一)

1、EF SQL监控工具目前采用SQLServer 自带的SQL Server Profiler来监控执行的sql&#xff0c;或者采用第三方插件MiniProfiler&#xff0c;具体用法可以网上查一下。2、EF使用SQlQuery 直接写sqlEF效率低于ADO.NET是因为LINQ-TO-SQL的过程消耗了时间。而使用SqlQuery则可以直接…

解决Genymotion下载设备失败的方法(Connection Timeout)

一直下载不下来&#xff0c;报错。 解决办法&#xff1a; 打开 C:\Users\用户名\AppData\Local\Genymobile目录 打开genymotion.log文件&#xff0c;在里面最下面几行&#xff0c;找到如下日志 [Debug] Downloading file "http://files2.genymotion.com/dists/4.4.4/ova/…

寻仙服务器要维护多久,寻仙手游几天开一个区

摘要寻仙手游最新开服时间表IOS和安卓&#xff0c;寻仙手游什么时候新增开服&#xff0c;开服时间公告。我们将于8月17日(周四)凌晨5:00-9:00对全服进行停机更新&#xff0c;请您提前保存游戏进程&#xff0c;安全下线。听到很多小伙伴都在讨论寻仙手游几天开一个区&#xff0c…

Linux常用初级指令介绍

touch 文件名 ------可创建一个文件&#xff08;白色的字体&#xff09;rm * -rf -------删除当前路径下的全部文件Ctrlc :----强行终止当前程序Ctrld -----退出终端Ctrls ----暂停当前程序&#xff0c;然后按下任意键恢复运行Ctrlz ----将当前程序放在后台运行&#xff0c;回…

如何写出安全的API接口

通过园友们的讨论&#xff0c;以及我自己查了些资料&#xff0c;然后对接口安全做一个相对完善的总结&#xff0c;承诺给大家写个demo&#xff0c;今天一并放出。对于安全也是相对的&#xff0c;下面我来根据安全级别分析1.完全开放的接口有没有这样的接口&#xff0c;谁都可以…

Linux系统文件编程(1)

打开文件 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);open----返回的是文件描述符是整形数&#xff08;文件描述符在形式上是一个非负整数。实际上&#xff0c;它是一个索引值&#xff0c;指向内核为每一个进程所维…

【收集】常用的cmd命令

运行操作CMD命令&#xff1a;开始&#xff0d;>运行&#xff0d;>键入cmd或command(在命令行里可以看到系统版本、文件系统版本)CMD命令锦集1. gpedit.msc-----组策略2. sndrec32-------录音机3. Nslookup-------IP地址侦测器 &#xff0c;是一个 监测网络中 DNS 服务器是…