#MongoDB使用: 条件操作,排序,索引,分页查询,聚合函数##mongodb条件查询 > use study switched to db study > db.student.insert({"name":"张三","age":18,"score":100,"sex":1}) WriteResult({ "nInserted" : 1 }) > db.student.insert({"name":"李四","age":20,"score":90,"sex":1}) WriteResult({ "nInserted" : 1 }) > db.student.insert({"name":"小红","age":19,"score":100,"sex":0}) WriteResult({ "nInserted" : 1 }) > db.student.insert({"name":"小明","age":19,"score":95,"sex":1}) WriteResult({ "nInserted" : 1 })首先要创建一个study数据库,并创建student集合,存入四条数据。 ```shell script1. 查询年龄大于19的学生。‘>‘==>‘gt‘ // ‘>=‘==>‘gte‘> db.student.find({"age":{$gt:19}}){ "_id" : ObjectId("5ea502960cf4f3a59d7d9850"), "name" : "李四", "age" : 20, "score" : 90, "sex" : 1 }2. 查询成绩小于等于95的学生 ‘<‘==>‘lt‘ // ‘<=‘==>‘lte‘> db.student.find({"score":{$lte: 95}}){ "_id" : ObjectId("5ea502960cf4f3a59d7d9850"), "name" : "李四", "age" : 20, "score" : 90, "sex" : 1 }{ "_id" : ObjectId("5ea502c70cf4f3a59d7d9852"), "name" : "小明", "age" : 19, "score" : 95, "sex" : 1 }3. 查询年龄在18-20之间的。 where age>18 and age <20> db.student.find({"age":{$lt:20,$gt:18}}){ "_id" : ObjectId("5ea502ae0cf4f3a59d7d9851"), "name" : "小红", "age" : 19, "score" : 100, "sex" : 0 }{ "_id" : ObjectId("5ea502c70cf4f3a59d7d9852"), "name" : "小明", "age" : 19, "score" : 95, "sex" : 1 }```#分页查询db.collection.find(query).limit(number)查询两条数据```shell script> db.student.find(){ "_id" : ObjectId("5ea502830cf4f3a59d7d984f"), "name" : "张三", "age" : 18, "score" : 100, "sex" : 1 }{ "_id" : ObjectId("5ea502960cf4f3a59d7d9850"), "name" : "李四", "age" : 20, "score" : 90, "sex" : 1 }{ "_id" : ObjectId("5ea502ae0cf4f3a59d7d9851"), "name" : "小红", "age" : 19, "score" : 100, "sex" : 0 }{ "_id" : ObjectId("5ea502c70cf4f3a59d7d9852"), "name" : "小明", "age" : 19, "score" : 95, "sex" : 1 }> db.student.find().limit(2){ "_id" : ObjectId("5ea502830cf4f3a59d7d984f"), "name" : "张三", "age" : 18, "score" : 100, "sex" : 1 }{ "_id" : ObjectId("5ea502960cf4f3a59d7d9850"), "name" : "李四", "age" : 20, "score" : 90, "sex" : 1 }```##跳过skip查询第2-3条数据```shell script> db.student.find().limit(2).skip(1){ "_id" : ObjectId("5ea502960cf4f3a59d7d9850"), "name" : "李四", "age" : 20, "score" : 90, "sex" : 1 }{ "_id" : ObjectId("5ea502ae0cf4f3a59d7d9851"), "name" : "小红", "age" : 19, "score" : 100, "sex" : 0 }```通过使用skip和limit我们可以进行分页查询。先在集合中插入10条记录。```shell script> db.student.find(){ "_id" : ObjectId("5ea502830cf4f3a59d7d984f"), "name" : "张三", "age" : 18, "score" : 100, "sex" : 1 }{ "_id" : ObjectId("5ea502960cf4f3a59d7d9850"), "name" : "李四", "age" : 20, "score" : 90, "sex" : 1 }{ "_id" : ObjectId("5ea502ae0cf4f3a59d7d9851"), "name" : "小红", "age" : 19, "score" : 100, "sex" : 0 }{ "_id" : ObjectId("5ea502c70cf4f3a59d7d9852"), "name" : "小明", "age" : 19, "score" : 95, "sex" : 1 }{ "_id" : ObjectId("5ea508010cf4f3a59d7d9853"), "name" : "王二", "age" : 22, "score" : 88, "sex" : 1 }{ "_id" : ObjectId("5ea508140cf4f3a59d7d9854"), "name" : "马六", "age" : 21, "score" : 88, "sex" : 0 }{ "_id" : ObjectId("5ea508280cf4f3a59d7d9855"), "name" : "小芳", "age" : 18, "score" : 88, "sex" : 0 }{ "_id" : ObjectId("5ea5083a0cf4f3a59d7d9856"), "name" : "小李", "age" : 18, "score" : 93, "sex" : 1 }{ "_id" : ObjectId("5ea5084a0cf4f3a59d7d9857"), "name" : "小张", "age" : 18, "score" : 98, "sex" : 1 }{ "_id" : ObjectId("5ea5085d0cf4f3a59d7d9858"), "name" : "小强", "age" : 22, "score" : 70, "sex" : 1 }```查询第3页数据,每页3条。 db.collection.find().limit(3).skip((3-1)*3) <==> limit (x-1)*3, 3;```shell script> db.student.find().skip(2*3).limit(3){ "_id" : ObjectId("5ea508280cf4f3a59d7d9855"), "name" : "小芳", "age" : 18, "score" : 88, "sex" : 0 }{ "_id" : ObjectId("5ea5083a0cf4f3a59d7d9856"), "name" : "小李", "age" : 18, "score" : 93, "sex" : 1 }{ "_id" : ObjectId("5ea5084a0cf4f3a59d7d9857"), "name" : "小张", "age" : 18, "score" : 98, "sex" : 1 }```##排序还是上面的集合,按照年龄升序排序。 db.collection.find(query).sort({key:1}) 1表示升序,-1表示降序```shell script> db.student.find().sort({age:1}){ "_id" : ObjectId("5ea502830cf4f3a59d7d984f"), "name" : "张三", "age" : 18, "score" : 100, "sex" : 1 }{ "_id" : ObjectId("5ea508280cf4f3a59d7d9855"), "name" : "小芳", "age" : 18, "score" : 88, "sex" : 0 }{ "_id" : ObjectId("5ea5083a0cf4f3a59d7d9856"), "name" : "小李", "age" : 18, "score" : 93, "sex" : 1 }{ "_id" : ObjectId("5ea5084a0cf4f3a59d7d9857"), "name" : "小张", "age" : 18, "score" : 98, "sex" : 1 }{ "_id" : ObjectId("5ea502ae0cf4f3a59d7d9851"), "name" : "小红", "age" : 19, "score" : 100, "sex" : 0 }{ "_id" : ObjectId("5ea502c70cf4f3a59d7d9852"), "name" : "小明", "age" : 19, "score" : 95, "sex" : 1 }{ "_id" : ObjectId("5ea502960cf4f3a59d7d9850"), "name" : "李四", "age" : 20, "score" : 90, "sex" : 1 }{ "_id" : ObjectId("5ea508140cf4f3a59d7d9854"), "name" : "马六", "age" : 21, "score" : 88, "sex" : 0 }{ "_id" : ObjectId("5ea508010cf4f3a59d7d9853"), "name" : "王二", "age" : 22, "score" : 88, "sex" : 1 }```##索引 createIndex(key,options)```shell script> db.student.createIndex({"score":1}){ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1}```{"score":1},表示创建score的索引,升序排序。还可以写复合索引{"score":1,"age":-1}## 聚合查询男女生数量,男为1,女为0```shell script> db.student.aggregate([{$group:{"_id":"$sex",num_tutorial:{$sum:1}}}]){ "_id" : 0, "num_tutorial" : 3 }{ "_id" : 1, "num_tutorial" : 7 }```
MongoDB使用: 条件操作,排序,索引,分页查询,聚合函数
标签:tom 记录 call automatic mongodb使用 aggregate and rip iter
小编还为您整理了以下内容,可能对您也有帮助:
mongo中的高级查询之聚合操作(distinct,count,group)与数据去重
Mongodb中自带的基本聚合函数有三种:count、distinct和group。下面我们分别来讲述一下这三个基本聚合函数。
(1)count
作用:简单统计集合中符合某种条件的文档数量。
使用方式:db.collection.count(<query>)或者db.collection.find(<query>).count()
参数说明:其中<query>是用于查询的目标条件。如果出了想限定查出来的最大文档数,或者想统计后跳过指定条数的文档,则还需要借助于limit,skip。
举例:
db.collection.find(<query>).limit();
db.collection.find(<query>).skip();
(2)distinct
作用:用于对集合中的文档针进行去重处理
使用方式:db,collection.distinct(field,query)
参数说明:field是去重字段,可以是单个的字段名,也可以是嵌套的字段名;query是查询条件,可以为空;
举例:
db.collection.distinct("user",{“age":{$gt:28}});//用于查询年龄age大于28岁的不同用户名
除了上面的用法外,还可以使用下面的另外一种方法:
db.runCommand({"distinct":"collectionname","key":"distinctfied","query":<query>})
collectionname:去重统计的集合名,distinctfield:去重字段,,<query>是可选的条件;
举例:
这两种方式的区别:第一种方法是对第二种方法的封装,第一种只返回去重统计后的字段值集合,但第二种方式既返回字段值集合也返回统计时的细节信息。
(3)group
作用:用于提供比count、distinct更丰富的统计需求,可以使用js函数控制统计逻辑
使用方式:db.collection.group(key,rece,initial[,keyf][,cond][,finalize])
备注说明:在2.2版本之前,group操作最多只能返回10000条分组记录,但是从2.2版本之后到2.4版本,mongodb做了优化,能够支持返回20000条分组记录返回,如果分组记录的条数大于20000条,那么可能你就需要其他方式进行统计了,比如聚合管道或者MapRece;
===========================================================
mongo中的高级查询之聚合操作(distinct,count,group)
1.distinct的实现:
2.count的实现
3.group的实现
(1).分组求和:类似于mysql中的 select act,sum(count) from consumerecords group by act
(2).分组求和,过滤。类似mysql中的select act,sum(count) from consumerecords group by act having act='charge';
(3).将时间格式化并且按时间分组求count,不推荐使用这种方法。
db.playerlogs.aggregate({ concat:[{ year:" substr:[{ start"},0,4]},{ dayOfMonth:" group:{_id:" sum:1}}},{$sort:{con:1}}) ;
group按时间分组(时间格式化)
http://www.tuicool.com/articles/EjUnQz
javascriptz中时间的相关函数参考:
http://blog.csdn.net/npp616/article/details/7181730
(4).group 分组方法实现的讲解。
group 的完整语法是。
参数解释:
key:需要分组的键或是函数(function),group分组实例3中的key就是一个函数值
initial:声明并且初始化变量。每一组共享一个变量值。多个变量之间用逗号隔开
$rece:循环体,集合中有多少个文档,就会循环多少次。函数(function)中变量doc表示当前文档对象,
prev表示累积处理的结果对象(这个地方可能描述的不是很情况,自己慢慢体会)
finalize:可选参数,可以简单理解为对分组之后的结果的再次处理,doc表示group之后的文档对象(这一步也是一个循环体
condition:可选参数,对已经分组好的结果进行过滤,有点类似于mysql中的having
4.mapRece:暂缺,要想玩转这个方法需要有很强的JavaScript功能。
据说mapRece 可以实现很复杂的查询,可以将一个复杂的查询分拆到多个机器上运行,
然后把各个结果集组合起来,形成最终结果。但是很慢。
maprece用法大全
http://www.cnblogs.com/yuechaotian/archive/2013/02/22/2922268.html
maprece性能调优
http://www.iteye.com/news/28013
数组中去除重复值示例
http://www.cnblogs.com/sosoft/archive/2013/12/08/3463830.html
5.db.runCommand的相关命令.
db.runCommand({distinct:"consumerecords",key:"userId"}):键值去重 类似于mysql中的 select distinct userId from consumerecords
db.runCommand({distinct:"consumerecords",key:"userId"}).values.length:去重之后求记录数,类似于mysql中的 select count(distinct userId) from consumerecords
db.runCommand({distinct:"consumerecords",key:"userId",query:{act:"charge"}}):去重之后求记录数,类似于mysql中的 select distinct userId from consumerecords where act="charge"
db.runCommand(
... {
... group:
... {
... ns:"test2", # 集合名
... key:{iname:true}, # 分组字段
... initial:{dd:0}, # 按照来初始化该值
... rece之后 ,function返回的值
... {
... prev.dd=doc.iage+prev.dd #
... }
...
... }
... }
... )
数值以字符串形式存储的解决方案:
db.runCommand(
{
group:
{
ns:"consumerecords",
key:{act:true},
initial:{ct:100,tt:0},
$rece:function(doc,prev)
{
},
}
}
)
去重
1, 直接使用distinct 语句查询, 这种查询会将所有查询出来的数据返回给用户, 然后对查询出来的结果集求总数(耗内存,耗时一些)
var len = db.student.distinct("name",{"age" : 18}).length;
print(len)
注,使用这种方法查询时,查询的结果集大于16M 时会查询失败,失败信息如下:
{“message” : “distinct failed: MongoError: distinct too big, 16mb cap”,”stack” : “script:1:20”}
2, 使用聚合函数,多次分组统计结果,最终将聚合的结果数返回给用户
db.student.aggregate([
{ project:{"name":true}},
{ name"}},
{ sum:1}}}
])
注,这种查询数据量大时就不会出现如上查询失败的情况,而且这种查询不管是内存消耗还是时间消耗都优于上面一种查询
ps:根据id分组,id指定为组合项的话,因为id不会重复,所以作用相当于把组合项去重了。
假如现在需要拿出collection的其他field的话,可以使用$push关键字
// 根据name和sex分组
// 把分组后的name,sex,age放到对应的Document下,形成一个数组
db.student.aggregate(
[
{
name", sex: " push: " push: " push: "$age"}
}
}
]
). forEach(function(x){
db.temp.insert(
{
name: x.name,
sex : x.sex,
age: x.age
}
);
});
mongoDB应用篇-mongo聚合查询
如果我们在日常操作中,将部分数据存储在了MongoDB中,但是有需求要求我们将存储进去的文档数据,按照一定的条件进行查询过滤,得到想要的结果便于二次利用,那么我们就可以尝试使用MongoDB的聚合框架。
前面我们在学习文档查询的过程中,也介绍过一些查询的操作符,其中就有一部分是简单的查询聚合函数,例如 count 、 distinct 、 group 等,如果是简单的数据分析过滤,完全可以使用这些自带的聚合函数以及查询的操作符来完成文档的过滤查询操作
如果我们遇到了一些数据需要跨多个文本或者统计等操作,这个时候可能文档自身也较为复杂,查询操作符已经无法满足的时候,这个时候就需要使用MongoDB的聚合查询框架了。
使用聚合框架可以对集合中的文档进行变换和组合查询,基本上我们使用的时候,都是使用多个构件创建一个管道,用于对一连串的文档进行处理。这里的构件包括 筛选(filter) 、 投射(projecting) 、 分组(grouping) 、 排序(sorting) 、 (limiting) 以及 跳过(skipping)
MongoDB中需要使用聚合操作,一般使用 aggregate 函数来完成多个聚合之间的连接,aggregate() 方法的基本语法格式如下 :
现在假设我们有个集合articles,里面存储了文章的集合,大致如下:
但这时我们需要查询出来每一个作者写的文章数量,需要使用aggregate()计算 ,大致如下:
输出的结果为:
通过这个简单的案例我们就能输出想要的数据和属性名,大概分析一下刚刚的聚合查询语句, by_user字段进行分组,代表每个用户一条数据,而num_tutorial则是定义了数值类型计算的结果字段,$sum则是计算总和,相当于每个用户出现一次,都会+1,最终计算出来的总和通过num_tutorial字段进行输出
注:如果管道没有给出预期的结果,就需要进行调试操作,调试的时候,可以尝试先给一个管道操作符的条件,如果这个时候查询出来的结果是我们想要的,那么我们需要再去指定第二个管道操作符,依次操作,最后就会定位到出了问题的操作符
前面我们提到聚合查询会使用管道操作符,而每一个操作符就会接受一连串的文档,对这些文档进行一些类型转换,最后将转换以后的文档结果传递给下一个管道操作符来执行后续的操作,如果当前是最后一个管道操作符,那么则会显示给用户最后的文档数据。不同的管道操作符是可以按照顺序组合在一起使用,并且可以被重复执行多次,例如我们可以先使用$match然后再去、 match操作。
match管道操作符可以使用$gt、$lt、$in等操作符,进行过滤,不过需要注意的是不能在$match管道操作符中使用空间地理操作符。
在实际使用的过程中,尽可能的将 match操作符以后,再去投射或者执行分组操作的话,是可以利用索引的。
相比较一般的查询操作而言,使用管道操作,尤其是其中的投射操作更加强大。我们可以在查询文档结束以后利用 $project 操作符从文档中进行字段的提取,甚至于我们可以重命名字段,将部分字段映射成我们想要展示出去的字段,也可以对一部分字段进行一些有意义的处理。需要注意的是, $project 操作符可以传入两个参数,第一个是需要处理的属性名称,第二个则是0或者1,如果传入1,则代表当前的属性是需要显示出来的,如果是0或者不写,默认都是代表这个字段不需要显示出来
当然第二个参数也可以是一个表达式或者查询条件,满足当前表达式的数据也可以进行显示,接下来我们先准备一点数据:
接下来,我们来查询,条件是item字段为abc,quantity要大于5,并且我们只要item和price字段的结果,其他都排除掉:
可以看到结果为:
如果我们想要在原基础上改变某个字段的名称,例如将item改为item_code,可以利用$来完成,如下:
可以看到我们指定的名称item_code,而这个别名对应的字段item使用$作为前缀标记,代表将item字段映射为item_code,可以看到结果:
我们在投影的时候,除了可以将某个字段映射成其他字段以外,还可以针对某个字段进行一些简单的运算,最常见的就是 四则运算 ,即
加法( subtract )、乘法( divide )、求模( $mod ) ,
除此之外,还支持对字段进行 关系运算 (大小比较( " eq" )、大于( " gte" )、小于( " lte" )、不等于( " ifNull" ) )、
逻辑运算 (与( " or" )、非 ( " concat" )、截取( " toLower" ) )等
我们基于上面的需求,假设每一个价格是按照元为单位,现在要求输出W为单位,那么我们就需要对price进行除法运算,如下:
除此之外,我们也可以将计算完毕的price改名为priceW,即:
可以看到输出的结果为:
这时有一个需求,要求我们返回数据的同时还要yyyy-MM-dd格式的时间字符串,这个时候我们就需要对date字段进行时间函数和字符串混合处理了,如下:
这里需要注意的一点是, year:" substr函数将date字段的结果截取成字符串即可实现拼接
group的_id上,代表按照当前字段进行分组,例如,我们这里根据item进行分组:
在我们针对某个字段进行分组以后,我们可以针对每个分组进行一些操作符的使用,常见的例如: $sum 、 $avg 、 $min 、 $max 、 $first 、 $last 。
$avg 操作符用来返回每一个分组内的平均值
现在我们基于前面item的分组,我们想要算出来每个组内的平均价格是多少,如下:
$min 和 $max 操作符用于返回分组内最大的值和最小的值
除了平均值以外,我们现在将最贵的和最便宜的价格也要列出来,这个时候就可以使用这两个操作符了,如下:
$first 、 $last 则是可以获取当前分组中第一个或者最后一个的某个字段的结果,如下:
除此之外,我们还可以在分组的时候使用数组操作符,例如 $addToSet 可以判断,当前数组如果不包含某个条件,就添加到当前数组中, $push 则不管元素是否存在,都直接添加到数组中
注意:大部分管道操作符都是流式处理的,只要有新的文档进入,就可以对新的文档进行处理,但是 $group 代表必须收到全部文档以后才可以进行分组操作,才会将结果传递给后续的管道操作符,这就意味着,如果当前mongo是存在分片的,会先在每个分片上执行完毕以后,再把结果传递mongos进行统一的分组,剩下的管道操作符也不会在每个分片,而是mongos上执行了
如果我们现在遇到一些文档比较复杂,比如存在内嵌文档的存在,某个属性里面嵌套了一个数组,但是我们需要对内嵌的数组文档进行分析过滤等查询处理,这个时候就可以使用 $unwind 操作符将每一个文档中的嵌套数组文件拆分为一个个的文档便于进行后续的处理,例如我们需要将之前的set集合中关于请求的url以及ip的信息拆分出来,原始的格式如下:
我们可以使用命令进行拆分,如下:
结果为:
可以看到数据则是按照每一条信息的方式展示出来了,方便后续的计算以及输出,但是需要注意的一点是,这种方式,如果该文档中没有拆分的字段,或者是空数组,默认会直接排除,如果我们需要空数组等也输出计算出来,则可以指定 preserveNullAndEmptyArrays 参数,设置为true,则代表空数组或者不存在的文档也要拆分输出出来,即:
我们可以在管道查询的过程中,按照某个属性值或者多个属性的结果进行顺序排序,排序的方式与普通查询操作符中的sort操作符表现一致,与其他管道操作符一样,可以在任何阶段使用,但是,需要注意的一点是,建议在管道操作符第一阶段进行排序,因为此时的排序是可以触发索引的,如果在后续阶段进行排序,会消耗大量内存,并且耗时会很久,尤其是在有 $group 的情况下,如果放在 $group 操作符后面,会发现等到的时间很久,不仅仅是无法触发索引的问题,还和 $group 操作符是等待所有数据完毕才会触发的特性有关,因此需要格外注意。
结果如下,按照我们想要的结果进行了排序:
limit,只返回前两条数据,如下:
结果如下:
除了 skip,与之前的查询操作符作用也是一样的,用于在已经查询完毕的结果集中跳过前N条数据以后进行返回,我们将$skip加在刚刚的查询后面,如下:
这个时候可以看到返回的结果为空,什么结果都没有了,这是因为前一步管道已经了仅仅返回2条,而接着我们又跳过了前两条文档,因此返回的结果为空,我们将顺序调换一下,看看:
可以看到结果如下,与刚才的结果无异:
管道查询操作符有很多,除了上面学习的常用的部分,还有几十个,需要了解全部的可以参考官网:
https://docs.mongodb.com/manual/reference/command/aggregate/
除此之外,我们在学习的过程中了解到,部分查询操作符是可以触发索引的,例如 $project 、 $group 或者 $unwind 操作符,因此我们也建议 如果可以的话,尽量先使用这类管道操作符进行数据过滤,可以有效减少数据集大小和数量,而且管道如果不是直接从原先的集合中使用数据,那就无
法在筛选和排序中使用索引 ,例如我们先进行管道操作,再去将过滤好的数据进行 $sort 排序,会导致无法使用索引,效率大幅度下降,因此如果我们需要涉及到 $sort 操作的时候,如果可以尽可能在最开始就处理,这个时候可以使用索引,效率较高,然后再去进行管道查询筛选与分组等其他操作,可以有效的提高查询的效率。另外需要注意的一点是,在 MongoDB中会对每一个管道查询做,例如某一步管道查询操作导致内存占用超过20%,这个时候就会报错,无法继续使用管道 ,因为mongoDB本身每次最大是16Mb的数据量,为了尽可能避免或者减少这种问题,建议可以考虑尽可能的使用 $match 操作符过滤无用数据,减少数据总大小。同时也 因为管道查询是多步执行,例如 $group 则是等待所有数据完毕才会执行,因此可能会导致整体执行时间较久 ,也因为这样,才不建议在较高的实时查询需求上使用管道和查询,而是在 设计的时候尽可能直接使用查询操作符进行数据查询,触发更多的索引,更快的销量查询出来想要的结果。
MongoDB 索引
Nothing like a little truth to sober you up.
唯有事实最能让人清醒。
索引支持在MongoDB中高效地执行查询。如果没有索引,MongoDB必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
如果查询存在适当的索引,MongoDB可以使用该索引必须检查的文档数。
索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB还可以使用索引中的排序返回排序结果。
官网文档: https://docs.mongodb.com/manual/indexes/
MongoDB索引使用B树数据结构(确切的说是B-Tree,MySQL是B+Tree)
MongoDB的索引可以分为:单字段索引、复合索引以及地理空间索引等。
单字段索引:MongoDB支持在文档的单个字段上创建用户定义的升序/降序索引,称为单字段索引(Single Field Index)。
对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为MongoDB可以在任何方向上遍历索引。
复合索引:MongoDB还支持多个字段的用户定义索引,即复合索引(Compound Index)。
复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 { userid: 1, score: -1 } 组成,则索引首先按userid正序排序,然后在每个userid的值内,再在按score倒序排序。
其他索引:
地理空间索引(Geospatial Index):为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。
文本索引(Text Indexes):MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如“the”、“a”、“or”),而将集合中的词作为词干,只存储根词。
哈希索引(Hashed Indexes):为了支持基于散列的分片,MongoDB提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。
查看索引
返回一个集合中的所有索引的数组
语法格式 : db.collection.getIndexes()
提示 :该语法命令运行要求是MongoDB 3.0+
示例
结果中显示的是默认 _id 索引。
默认_id索引 :MongoDB在创建集合的过程中,在 _id 字段上创建一个唯一的索引,默认名字为 id ,该索引可防止客户端插入两个具有相同值的文档,您不能在_id字段上删除此索引。
注意 :该索引是唯一索引,因此值不能重复,即 _id 值不能重复的。在分片集群中,通常使用 _id 作为片键。
创建索引
在集合上创建索引。
语法格式 : db.collection.createIndex(keys, options)
参数说明 :
options(更多选项)列表:
注意 :在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex() ,之后的版本使用了 db.collection.createIndex() 方法, ensureIndex() 还能用,但只是 createIndex() 的别名。
实例
移除索引
可以移除指定的索引,或移除所有索引
语法格式 : db.collection.dropIndex(index) 或移除所有索引 db.collection.dropIndexes()
参数说明 :
实例
提示 : _id 的字段的索引是无法删除的,只能删除非 _id 字段的索引。
执行计划
分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是否基于索引查询等。
那么,通常,我们想知道,建立的索引是否有效,效果如何,都需要通过执行计划查看。
语法格式 : db.collection.find(query,options).explain(options)
实例
涵盖查询Covered Queries
当查询条件和查询的投影仅包含索引字段时,MongoDB直接从索引返回结果,而不扫描任何文档或将文档带入内存。 这些覆盖的查询可以非常有效。
我的理解是类似于mysql的索引覆盖,无须回表查询。
实例
有故事的人,通常不喜欢讲故事。不想在嘴上卖力,是想在心中开发能量。沉默,是一种负重的坚强,是一种韬光养晦的低调。少说多做,才是最有力的践行。
mongodb使用场景是什么?
适用场合
(1)网站数据:MongoDB适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
(2)缓存:由于性能很高,MongoDB也适合作为信息基础设施的缓存层。在系统重启之后,由MongoDB搭建的持久化缓存层可以避免下层的数据源过载。
(3)大尺寸,低价值的数据。
(4)高伸缩性的场景:MongoDB适合由数十或数百台服务器组成的数据库。
(5)用于对象及JSON数据的存储:MongoDB的BSON数据格式适合文档化格式的存储及查询。
扩展资料
功能
1、面向集合的存储:适合存储对象及JSON形式的数据。
2、动态查询:MongoDB支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
3、完整的索引支持:包括文档内嵌对象及数组。MongoDB的查询优化器会分析查询表达式,并生成一个高效的查询计划。
4、查询监视:MongoDB包含一系列监视工具用于分析数据库操作的性能。
5、复制及自动故障转移:MongoDB数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目标是提供冗余及自动故障转移。
6、高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)。
7、自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器