一、索引详讲
1、创建简单索引
   准备数据,创建books文档并插入200000条数据,如下:
   for(var i=0;i<200000;i++){
    db.books.insert({number:i,name:i+"book"})
   }
  1.1、先检验一下查询性能
     var start=new Date()
     db.books.find({number:65888})
     var end=new Date()
     end-start
  2.2、为number创建索引
    db.books.ensureIndex({number:1})
  3.3、再执行第一次查询的代码,可以看出有数量级的性能提升,大概10倍以上。

 2、索引使用需要注意的地方
 2.1、创建索引的时候,注意1是正序创建索引,-1是倒序创建索引。
 2.2、索引的创建,在提高查询性能的同时,会影响增删改的性能;
      对于经常查询少插入的文档可以考虑用索引。
 2.3、符合索引要注意索引的先后顺序。
 2.4、每个键全建立索引不一定就能提高性能,索引不是万能的。
 2.5、在做排序工作的时候,如果是超大数据量,也可以考虑加上索引,用来提高排序的性能。

3、索引的名称
3.1、用VUE查看索引名称,如下图:

MongoDB学习笔记系列:(五) 索引详解 _索引详解 空间索引

3.2、创建索引同事指定索引的名字
    db.books.ensureIndex({name:-1},{name:"bookname"})

4、唯一索引
4.1、如何解决文档books不能插入重复的数值
     建立唯一索引
  db.books.ensureIndex({name:1},{unique:true})
     测试
  db.books.insert({name:"1book"})
错误信息:E11000 duplicate key error index: foorbar.books.$name_1  dup key: { : "1book" }

5、过滤重复值
5.1、如果建立唯一索引之前,已经有重复数据,如何处理?
db.books.ensureIndex({name:1},{unique:true,dropDups:true})

6、Hint
6.1、如何强制查询使用指定的索引?
db.books.find({name:"1book",number:1}).hint({name:1})
指定索引必须是已经创建好的索引(包括顺序),否则会报如下错误:
error: { "$err" : "bad hint", "code" : 10113 }

7、explain
7.1、如何详细查看本次查询使用哪个索引和查询数据的状态信息
db.books.find({name:"1book"}).explain()
返回结果,如下所示:
> db.books.find({name:"1book"}).explain()
{
        "cursor" : "BtreeCursor name_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 1,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 1,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "name" : [
                        [
                                "1book",
                                "1book"
                        ]
                ]
        },
        "server" : "PC-20110917QHJT:27017"
}

"cursor" : "BtreeCursor name_1"  使用索引
"nscanned" : 1   查到几个文档
 "millis" : 0   查询时间,0是很不错的性能

二、索引管理
8、system.indexes 
8.1、在shell中,查看数据库已经建立的索引。如下:
db.system.indexes.find()
db.system.namespaces.find()

9、后台执行
9.1、执行创建索引的过程会暂时锁表问题,如何解决?
    为了不影响查询,我们可以让索引的创建过程在后台执行。
    db.books.ensureIndex({number:1},{true})

10、删除索引
10.1、批量和精确删除索引
 db.runCommand({dropIndexes:"books",index:"name_1"}) 精确删除索引
 db.runCommand({dropIndexes:"books",index:"*"})   批量删除索引

三、空间索引
11、mongoDB提供强大的空间索引,可以查询出一定范围的地理坐标。示例如下:
准备数据map.txt,如下图:

MongoDB学习笔记系列:(五) 索引详解 _索引详解 空间索引_02

首先,添加2D索引(默认会建立一个[-180,180]之间的2D索引)
 db.map.ensureIndex({"gis":"2d"},{min:-1,max:201})
11.1、查询出距离点(70,180)最近的3个点
 db.map.find({"gis":{$near:[70,180]}},{gis:1,_id:0}).limit(3)//$near操作符表示中心点;如果没有指定limit,其默认值为100。
11.2、查询以点(50,50)和(190,190)为对角线的正方形中的所有点
 var box=[[50,50],[190,190]];//定义一个矩形区域
 db.map.find({"gis":{"$within":{"$box":box}}},{gis:1,_id:0})//$box 矩形查找
11.3、查询出以圆心为(55,80),半径为50,规则下的圆心面积中的点
 var center=[55,80];//定义中心点
 var radius=50;//定义半径
 db.map.find({"gis":{"$within":{"$center":[center,radius]}}});//$center 圆形查找(注意这里是数组传递)