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"选项,查询就是针对不变的集合视图运行的。
游标内幕:客户端游标以及客户端游标表示的数据库游标。

MongoDB学习笔记三:查询的更多相关文章

  1. MongoDB学习笔记三—增删改文档上

    插入insert 单条插入 > db.foo.insert({"bar":"baz"}) WriteResult({ }) 批量插入 > db.fo ...

  2. Mongodb学习笔记三(Mongodb索引操作及性能测试)

    第三章 索引操作及性能测试 索引在大数据下的重要性就不多说了 下面测试中用到了mongodb的一个客户端工具Robomongo,大家可以在网上选择下载.官网下载地址:http://www.robomo ...

  3. MongoDB学习笔记三 - MongooseAPI操作数据

    在上一篇我们讲了如何通过Mongoose想数据库动态添加数据, 接下来我们一起来看一下如何通过Mongoose来对数据库进行增删改查等一系列操作 Model 对象的方法 remove(cinditio ...

  4. MongoDB学习笔记六—查询下

    查询内嵌文档 数据准备 > db.blog.find().pretty() { "_id" : ObjectId("585694e4c5b0525a48a441b5 ...

  5. MongoDB学习笔记五—查询上

    数据准备 { , "goods_name" : "KD876", "createTime" : ISODate("2016-12- ...

  6. MongoDB学习笔记(三) 在MVC模式下通过Jqgrid表格操作MongoDB数据

    看到下图,是通过Jqgrid实现表格数据的基本增删查改的操作.表格数据增删改是一般企业应用系统开发的常见功能,不过不同的是这个表格数据来源是非关系型的数据库MongoDB.nosql虽然概念新颖,但是 ...

  7. mongodb 学习笔记 3 --- 查询

    在mongodb的查询中可以通过使用如下操作符进行深度查询 1.条件操作符 $gt  $gte : >  >=   {"age":{"$gt":18 ...

  8. Mongodb 学习笔记(三) .net core SDK

    首先添加 Nuget包  MongoDB.Driver 创建一个Model. public class Student { public ObjectId _id { get; set; } publ ...

  9. MongoDB 学习笔记之 查询表达式

    查询表达式: db.stu.find().count() db.stu.find({name: 'Sky'}) db.stu.find({age: {$ne: 20}},{name: 1, age: ...

随机推荐

  1. [Prodinner项目]学习分享_第一部分_Model层

    事先声明一下,小弟我是菜鸟一个,在研究大半天之后,基本会开发一些简单的功能了,特此分享一下,也为自己做一个笔记. 项目简介: MVC4 , EF5 , Code First , 多层架构 开发工具:V ...

  2. [Oracle] SQL*Loader 详细使用教程(2)- 命令行参数

    sqlldr工具   SQL*Loader的客户端工具是sqlldr,在操作系统的命令行下输入sqlldr,后面不接任何参数,将显示帮助信息如下所示(所有命令行参数的简单描述及其默认值),所以你并不需 ...

  3. 今天的感悟,对于python中的list()与w3c教程

    首先本来想百度一下python定义列表的时候用 list()与直接用[]有什么区别,其中没有找到相关直接资料,看到了W3c菜鸟教程中之前看到的tuple,不禁想起list(tuple)是用来将元组转换 ...

  4. Shell 语法之输入输出

    Linux 使用文件描述符标识每个文件对象.文件描述符是一个非负整数,可以唯一地标识会话中打开的文件.每个进程中最多可以有9个打开文件的描述符. Linux 标准文件描述符 文件描述符 缩写 描述 0 ...

  5. 【转】Spring jar包详解

    转载自:http://www.cnblogs.com/yanjunwu/archive/2013/04/06/3001927.html org.springframework.aop ——Spring ...

  6. 【ros】.bag文件

    Bags are typically created by a tool like rosbag They store the serialized message data in a file as ...

  7. php 对多维数组排序array_multisort

    php 对多维数组排序array_multisort 排序顺序标志: SORT_ASC - 按照上升顺序排序 SORT_DESC - 按照下降顺序排序 排序类型标志: SORT_REGULAR - 将 ...

  8. laravel Ajax post方式的使用

    以jquery ajax 的post的方式为例 验证邮箱输入格式是否正确 html <div class="fl"> <input type="emai ...

  9. MAC air 安装redis-3.0.6

    redis版本: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Menlo; color: #c33720; background-colo ...

  10. SPSS常用基础操作(2)——连续变量离散化

    首先说一下什么是离散化以及连续变量离散化的必要性. 离散化是把无限空间中无限的个体映射到有限的空间中去,通俗点讲就是把连续型数据切分为若干“段”,也称bin,离散化在数据分析中特别是数据挖掘中被普遍采 ...