视频:MongoDB 教程三: 高级查询

 

MongoDB支持的查询语言非常强大,语法规则类似于面向对象的查询语言,可以实现类似关系数据库单表查询的绝大部分功能,并且由于 MongoDB可以支持复杂的数据结构,不受二维表形式的限制,因此MongoDB的查询速度非常快。下面介绍一些MongoDB的高级查询语法。

 

1、条件操作符查询

所谓条件操作符,就是< 、<=、>、>=这些符号,相应的查询语法如下:



db.collection.find({"key":{$gt:value}});  //大于  key>value
db.collection.find({"key":{$gte:value}});  //大于等于  key>=value
db.collection.find({"key":{$lt:value}});  //小于  key<value
db.collection.find({"key":{$lte:value}});  //小于等于  key<=value


上面的collection是一个集合名。key是要查询的字段,value是比较的范围。SQL为:select * from collection where key > (或者>=,<,<=)value,

 

2、$all匹配所有的值

这个操作与SQL语法的in类似,但是in只需要满足范围之一的值就可以,但是$all必须满足所有的值。例如



db.collection.find({age:{$all:[20,21]}});



可以查询出来{age:[20,21,22]}但是查询不出来{age:[20,22,23]},即一定要有20和21.

 

3、$in查询包含的值

这个与$all不一样,查询的值在$in给出的范围之内就都可以查出来。例如



db.collection.find({age:{$in:[20,21]}});



可以查询出来{age:[20,21,22]}{age:[20,22,23]}以及{age:[21,22,23]},即只需要有20或者21其中之一的都可以。

 

4、$exists判断字段是否存在

可以用$exists判断某一字段是否存在,例如查询存在age字段的记录


db.collection.find({age:{$exists:true}});


查询不存在age字段的记录



db.collection.find({age:{$exists:false}});


 

5、null值的处理

null值处理需要注意的是,不仅仅可以查询出来某一字段值为null的记录,还可以查出来不存在某一字段的记录。例如



db.collection.find({age:null})


可以查询出来age为null的记录,以及没有age字段的记录。如果我们需要只去查询存在age字段并且age字段的值为null的记录,需要配合exists操作,例如



db.collection.find({age:{"$in":[null],"$exists":true}});



即查询存在age字段的并且age字段值为null的记录

 

6、$mod取模运算

这个操作可以进行模运算。例如,查询age取模5等于3的记录



db.collection.find({age:{$mod:[5,3]}});


 

7、$ne不等于操作

可以查询不等于某一字段的数据,例如,查询age不等于20的记录



db.collection.find({age:{$ne:20}});



 

8、$nin不包含操作

这个与$in相反,查询不包含某一字段的记录,例如查询age不等于20,21,22的记录



db.collection.find({age:{$nin:[20,21,22]}});



 

9、count查询记录条数

这个可以用来知道查询到记录的条数,例如查询age等于20的记录数目



db.collection.find({age:20}).count();



 

10、排序

用sort函数排序,例如按照age升序排列


db.collection.find().sort({age:1})


类似asc,

按照age降序排列



db.collection.find().sort({age:-1})



类似desc。同时也可以在find里面添加查询条件。

 

11、skip和limit语句

这个是用来跳过几条记录然后查询指定数目的记录,例如跳过3条记录查询其余记录的最前面5条,


db.collection.find().skip(3).limit(5);

find里面可以加条件,这个类似SQL:select * from collection limit(3,5)

 

12、JavaScript查询和$where查询

例如,查询age大于20的记录,可以分别用到如下的方式:



db.collection.find({age:{$gt:20}});



这是条件操作符方式,
 
 
db.collection.find({$where:"this.age > 3"});
 
 
这是$where方式,
 
 
db.collection.find("this.age > 3");
 
 
这是内部对象查询
 
 
func=function(){return this.age > 3;} db.collection.find(func)
 
 
这是JavaScript方式。这几种方式都是一样的效果。

13,存储过程

MongoDB也可以有存储过程。例如一个简单的SQL存储过程函数为
 
 
function addNum(x,y){
return x+y;
}
 
 
现在要将这个函数转化成MongoDB的存储过程。Mongo的存储过程是保存在db.system.js表中的,可以这么写
 
 
db.system.js.save({_id:"addNum",value:function(x,y){return x+y;}});
 
 
这样就创建了一个存储过程。我们可以对存储过程进行查看、修改和删除操作,例如查看所有的存储过程,
 
 
db.system.js.find()
 
 
,其余修改和删除类似对记录的操作。
调用创建好的存储过程,需要用到db.eval(),例如调用刚刚创建的addNum,是这样
 
 
db.eval("addNum(30,12)");
 
 
就可以得出答案是42。
同时,可以直接使用db.eval来创建存储过程并且直接调用,例如
 
 
db.eval(function(){return 30+12;});
 
 
可以直接得出42,这样可以知道使用db.eval可以直接进行算数运算,非常方便。
还有就是,存储过程可以处理数据库内部的操作,例如
 
 
db.system.js.save({_id:"getCount",value:function(){return db.collection.find({age:20}).count();}});
 
 
可以将db.collection中age为20的记录数目保存在getCount这个存储过程中,调用的时候这样
 
 
db.eval("getCount()");
 
 
就可以直接取得那个数目。

这样,MongoDB的高级查询语句就介绍完了,以上代码亲测有效!

$type



$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。

MongoDB 中可以使用的类型如下表所示:

类型

数字

备注

Double

1

 

String

2

 

Object

3

 

Array

4

 

Binary data

5

 

Undefined

6

已废弃。

Object id

7

 

Boolean

8

 

Date

9

 

Null

10

 

Regular Expression

11

 

JavaScript

13

 

Symbol

14

 

JavaScript (with scope)

15

 

32-bit integer

16

 

Timestamp

17

 

64-bit integer

18

 

Min key

255

Query with -1.

Max key

127

 

我们使用的数据库名称为"runoob" 我们的集合名称为"col",以下为我们插入的数据。

简单的集合"col":



>db.col.insert({
    title: 'PHP 教程', 
    description: 'PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['php'],
    likes: 200
})


>db.col.insert({title: 'Java 教程', 
    description: 'Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['java'],
    likes: 150
})


>db.col.insert({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '菜鸟教程',
    url: 'http://www.runoob.com',
    tags: ['mongodb'],
    likes: 100
})



使用find()命令查看数据:



> db.col.find()
{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "PHP 教程", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "php" ], "likes" : 200 }
{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Java 教程", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "java" ], "likes" : 150 }
{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb" ], "likes" : 100 }



MongoDB 操作符 - $type 实例

如果想获取 "col" 集合中 title 为 String 的数据,你可以使用以下命令:



db.col.find({"title" : {$type : 2}})



输出结果为:



{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "PHP 教程", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "php" ], "likes" : 200 }
{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Java 教程", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "java" ], "likes" : 150 }
{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb" ], "likes" : 100 }



MongoDB Limit与Skip方法



如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。

语法

limit()方法基本语法如下所示:



>db.COLLECTION_NAME.find().limit(NUMBER)



实例

集合 col 中的数据如下:



{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "PHP 教程", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "php" ], "likes" : 200 }
{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Java 教程", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "java" ], "likes" : 150 }
{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb" ], "likes" : 100 }



以上实例为显示查询文档中的两条记录:



> db.col.find({},{"title":1,_id:0}).limit(2)
{ "title" : "PHP 教程" }
{ "title" : "Java 教程" }
>



注:如果你们没有指定limit()方法中的参数则显示集合中的所有数据。


MongoDB Skip() 方法

我们除了可以使用limit()方法来读取指定数量的数据外,还可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。

语法

skip() 方法脚本语法格式如下:



>db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)



实例

以上实例只会显示第二条文档数据



>db.col.find({},{"title":1,_id:0}).limit(1).skip(1)
{ "title" : "Java 教程" }
>



注:skip()方法默认参数为 0 。

MongoDB 排序

在MongoDB中使用使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列。

语法

sort()方法基本语法如下所示:



>db.COLLECTION_NAME.find().sort({KEY:1})



实例

col 集合中的数据如下:



{ "_id" : ObjectId("56066542ade2f21f36b0313a"), "title" : "PHP 教程", "description" : "PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "php" ], "likes" : 200 }
{ "_id" : ObjectId("56066549ade2f21f36b0313b"), "title" : "Java 教程", "description" : "Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "java" ], "likes" : 150 }
{ "_id" : ObjectId("5606654fade2f21f36b0313c"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb" ], "likes" : 100 }



以下实例演示了 col 集合中的数据按字段 likes 的降序排列:



>db.col.find({},{"title":1,_id:0}).sort({"likes":-1})
{ "title" : "PHP 教程" }
{ "title" : "Java 教程" }
{ "title" : "MongoDB 教程" }
>



注: 如果没有指定sort()方法的排序方式,默认按照文档的升序排列。

MongoDB 正则表达式

正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。

许多程序设计语言都支持利用正则表达式进行字符串操作。

MongoDB 使用 $regex 操作符来设置匹配字符串的正则表达式。

MongoDB使用PCRE (Perl Compatible Regular Expression) 作为正则表达式语言。

不同于全文检索,我们使用正则表达式不需要做任何配置。

考虑以下 posts 集合的文档结构,该文档包含了文章内容和标签:



{
   "post_text": "enjoy the mongodb articles on tutorialspoint",
   "tags": [
      "mongodb",
      "tutorialspoint"
   ]
}



使用正则表达式

以下命令使用正则表达式查找包含 w3cschool.cc 字符串的文章



>db.posts.find({post_text:{$regex:"w3cschool.cc"}})


以上查询也可以写为:



>db.posts.find({post_text:/w3cschool.cc/})




不区分大小写的正则表达式

如果检索需要不区分大小写,我们可以设置 $options 为 $i。

以下命令将查找不区分大小写的字符串 w3cschool.cc:


>db.posts.find({post_text:{$regex:"w3cschool.cc",$options:"$i"}})


集合中会返回所有包含字符串 w3cschool.cc 的数据,且不区分大小写:



{
   "_id" : ObjectId("53493d37d852429c10000004"),
   "post_text" : "hey! this is my post on  W3Cschool.cc", 
   "tags" : [ "tutorialspoint" ]
}




数组元素使用正则表达式

我们还可以在数组字段中使用正则表达式来查找内容。 这在标签的实现上非常有用,如果你需要查找包含以 tutorial 开头的标签数据(tutorial 或 tutorials 或 tutorialpoint 或 tutorialphp), 你可以使用以下代码:



>db.posts.find({tags:{$regex:"tutorial"}})




优化正则表达式查询

  • 如果你的文档中字段设置了索引,那么使用索引相比于正则表达式匹配查找所有的数据查询速度更快。
  • 如果正则表达式是前缀表达式,所有匹配的数据将以指定的前缀字符串为开始。例如: 如果正则表达式为 ^tut ,查询语句将查找以 tut 为开头的字符串。

 

这里面使用正则表达式有两点需要注意:

正则表达式中使用变量。一定要使用eval将组合的字符串进行转换,不能直接将字符串拼接后传入给表达式。否则没有报错信息,只是结果为空!实例如下:


var name=eval("/" + 变量值key +"/i");


以下是模糊查询包含title关键词, 且不区分大小写:


title:eval("/"+title+"/i")    // 等同于 title:{$regex:title,$Option:"$i"}


 

 

原文/转自:MongoDB