一、简单介绍
我们上一篇介绍了索引基本操作,通过db.collection.createIndex(keys, options)语法创建索引,我们继续介绍地理空间索引、索引的限制,使我们在MongoDB时能提高查询效率。
索引的语法:
db.collection.createIndex(keys,options)
options 參数说明
二.地理空间索引
我们生活上用到地理位置越多越多。所以存储经纬度就多了,查地理位置就多了,为了提高在MongoDB查询效率,我们建立地理空间索引。
1.创建地理空间索引
语法:
db.collection.createIndex({ <location field> : "2d" , <additionalfield> : <value> } , {<index-specification options> } )
index-specification參数说明:
{ min : <lower bound> , max :<upper bound> }
我们常常创建经纬度的格式有几种,比如:location:[ 50, 40 ]、location :{ lng :50 ,lat : 40}
> db.places.find() { "_id" :ObjectId("55ad0df063ea39b3057bdeef"), "onumber" : 1,"date" : "2015-07 -01", "cname" :"zcy", "location" : [ -10, 100 ] } { "_id" :ObjectId("55ad0e0463ea39b3057bdef0"), "onumber" : 2,"date" : "2015-07 -02", "cname" :"zcy", "location" : [ 10, 60 ] } { "_id" :ObjectId("55ad0e1663ea39b3057bdef1"), "onumber" : 3,"date" : "2015-07 -03", "cname" :"zcy", "location" : [ 100, 150 ] } { "_id" :ObjectId("55ad0e2463ea39b3057bdef2"), "onumber" : 4,"date" : "2015-07 -04", "cname" : "zcy","location" : [ 150, 200 ] } { "_id" :ObjectId("55ad0e3263ea39b3057bdef3"), "onumber" : 5,"date" : "2015-07 -05", "cname" :"zcy", "location" : [ -100, 100 ] }
样例:
>db.places.createIndex({location:"2d"})
地理空间索引默认值的范围为-180到180,假设值已经存在超过了200时,就会建索引失败:
"errmsg" : "point not in interval of [ -180, 180 ] ::caused by :: { _id: ObjectId('55ad07bc63ea39b3057bdeed'),onumber: 5.0, date: "2015-07-05", cnam
e: "zcy", location: [ 100.0,200.0 ] }", "code" : 13027
我们能够建立一个二维地理空间索引的位置范围以外的默认。创建索引时使用最小和最大选项。
语法:
db.collection.createIndex( {<location field> : "2d" } , {min : <lower bound> , max : <upper bound> } )
样例:
>db.places.createIndex({location:"2d"},{min:-200,max:200})
地理空间索引默认值的范围为-200到200
2.查询平面上的点
我们能够使用$near或者geoNear Command查询。能够使用limit()函数,若不指定,默认是返回100条文档。
(1) 精确的查询
样例:
> db.places.find({location:[60,100]})
我们查询经纬度为[60,100]
(2) $near查询
我们须要查询范围内的经纬度有哪些
语法:
db.collection.find( {<location field> : {$near : [ <x> , <y> ] } } )
样例:
> db.places.find({location:{$near:[100,200]}})
我们查询目标点[100,200]距离近期的100个点。然后是按最接近的排序
(3)geoNearCommand查询
geoNear Command查询根db.collection.find()查询相似
语法:
db.runCommand( { geoNear:<collection>, near: [ <x> , <y> ] } )
样例:
> db.runCommand( {geoNear:"places", near: [ -100,100] } ) { "results" :[ { "dis" : 0, "obj" : { "_id" : ObjectId("55ad0e3263ea39b3057bdef3"), "onumber" : 5, "date" : "2015-07-05", "cname" : "zcy", "location" : [ -100, 100 ] } }, { "dis" : 90, "obj" : { "_id" : ObjectId("55ad0df063ea39b3057bdeef"), "onumber" : 1, "date" : "2015-07-01", "cname" : "zcy", "location" : [ -10, 100 ] } }, { "dis" : 117.04699910719626, "obj" : { "_id" : ObjectId("55ad0e0463ea39b3057bdef0"), "onumber" : 2, "date" : "2015-07-02", "cname" : "zcy", "location" : [ 10, 60 ] } }, { "dis" : 206.15528128088303, "obj" : { "_id" : ObjectId("55ad0e1663ea39b3057bdef1"), "onumber" : 3, "date" : "2015-07-03", "cname" : "zcy", "location" : [ 100, 150 ] } }, { "dis" : 269.2582403567252, "obj" : { "_id" : ObjectId("55ad0e2463ea39b3057bdef2"), "onumber" : 4, "date" : "2015-07-04", "cname" : "zcy", "location" : [ 150, 200 ] } } ], "stats" : { "nscanned" : NumberLong(5), "objectsLoaded" : NumberLong(5), "avgDistance" : 136.4921041489609, "maxDistance" : 269.2582403567252, "time" : 52 }, "ok" : 1 }
4.查询曲面上定义的点
(1)$box
(2)$polygon
( 3)$center(defines a circle)
这边就不做详细介绍了,能够到官方文档查看:http://docs.mongodb.org/manual/tutorial/query-a-2d-index/
三.索引的限制
我们第二章介绍索引的基本创建,我们如今创建索引时加上限制条件,比方唯一索引等
1. 唯一索引
对字段设置唯一索引时。能够保证字段都是唯一性
语法:
db.collection.createIndex({field1:boolean, field2:boolean },{unique: true})
(1)新建唯一索引
样例:
> db.orders.createIndex({onumber:1},{unique:true})
我们创建了onumber为唯一索引
当我们插入同样的onumber时。会新增失败
说明:我们在新建字段为唯一索引时。相应的字段不存在,索引会将其作为null存储,假设对文档新增第一条时,没保存字段相应的值时,会以null保存,第二条还是对指定字段相应的值,新增数据时,之前已经存在null。所以会导致新增失败。
(2)对文档中已经存在的同样的字段新建唯一索引
我们文档中已经有数据时。我们新建唯一索引
样例:
>db.orders.createIndex({onumber:1},{unique:true})
我们集合中的onumber字段值已经有反复,所以会导致创建唯一性索引失败
唯一索引不可以创建在具有反复值的键上,假设你一定要在这种键上创建,使用dropDups參数,系统对反复值的键上仅仅保留第一条记录,剩下的记录会被删除
样例:
>db.orders.createIndex({onumber:1},{unique:true,dropDups:true})
2. 索引的名称
我们之前在创建索引时,没指定索引名称,MongoDB会生成一个默认的索引名称,我们能够通过name參数来指定我们新建索引的名称
语法:
db.collection.createIndex({field1:boolean,field2:boolean },{name: "index_name"})
样例:
>db.orders.createIndex({onumber:1},{name:"index_onumber"})
我们onumber字段新建一个索引名称为index_onumber的索引
3. 后台方式创建索引
background 在创建索引时,会堵塞MongoDB其他操作,比方查询MongoDB时,background为trues时可指定以后台方式创建索引,默认值时false
语法:
db.collection.createIndex({{field1:boolean,field2:boolean }} },{background: true})
样例:
> db.orders.createIndex({cname:1},{background:true}<span style="font-size:18px;">)</span>
4. 稀疏索引
sparse:稀疏索引仅仅包括有索引字段的文档。即使索引字段包括空值,指数跳过缺少索引字段。
索引是“稀疏的”。由于它不包括集合的全部文档。与之相反。非稀疏索引中包括一个集合中的全部文档。这些文档中不包括索引字段的空值。
类似于$exists用来推断一个field是否存在
语法
db.collection.createIndex({{field1:boolean,field2:boolean }} },{ sparse: true})
样例:
>db.orders.createIndex({onumber:1},{sparse:true})
我们查询时。onumber为null为4条记录。我们以onumber为nul做为查询条件时。没使用到索引。
而我们以onumber为1作为查询条件时。有使用到索引。
稀疏索引仅仅包括有索引字段的文档。即使索引字段包括空值,指数跳过缺少索引字段
四、索引的信息
1. 强制索引
我们在对MongoDB查询时。能够使用hint强制用某个索引
语法:
db. collection.find().hint(“index_name”)
样例:
>db.orders.find({onumber:1}).hint("onumber_1")
我们强制使用onumber 字段索引名称为onumber_1的索引
MongoDB的查询优化器很智能,会替你选择该用哪个索引,多数情况下不须要指定的。
2. 运行计划
MongoDB 提供了一个 explain 命令让我们获知系统怎样处理查询请求。利用 explain 命令,我们能够非常好地观察系统怎样使用索引来加快检索,同一时候能够针对性优化索引。
>db.orders.find({onumber:1}).hint("onumber_1").explain() { "cursor" : "BtreeCursor onumber_1", "isMultiKey" : false, "n" : 1, "nscannedObjects" : 1, "nscanned" : 1, "nscannedObjectsAllPlans" : 1, "nscannedAllPlans" : 1, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 77, "indexBounds" : { "onumber" : [ [ 1, 1 ] ] }, "server" : "zhengcy-PC:27017", "filterSet" : false }
对一些比較重要的參数说明:
1) n:当前查询返回的文档数量。
2)millis:当前查询所需时间。毫秒数。
3)indexBounds:当前查询详细使用的索引。
4)nscanned:扫描document的行数。
5)cursor:返回游标类型(BasicCursor和BtreeCursor),我们这边使用BtreeCursor类型。
6)nscannedObjects:被扫描的文档数量。
7)scanAndOrder:是否在内存中排序。