我们上一篇介绍了索引基本操作,通过db.collection.createIndex(keys, options)语法创建索引,我们继续介绍地理空间索引、索引的限制,使我们在MongoDB时能提高查询效率。
索引的语法:
db.collection.createIndex(keys,options)
options 参数说明
我们生活上用到地理位置越多越多,所以存储经纬度就多了,查地理位置就多了,为了提高在MongoDB查询效率,我们建立地理空间索引。
1.创建地理空间索引
语法:
db.collection.createIndex({ : "2d" ,
: } ,
{ } )
index-specification参数说明:
{ min :
我们经常创建经纬度的格式有几种,例如: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( { : "2d" } ,
{min : , max : } )
例子:
>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( { :
{$near : [ , ]
} } )
例子:
> db.places.find({location:{$near:[100,200]}})
我们查询目标点[100,200]距离最近的100个点,然后是按最接近的排序
(3)geoNearCommand查询
geoNear Command查询根db.collection.find()查询相似
语法:
db.runCommand( { geoNear:, near: [ , ] } )
例子:
> 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})
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:是否在内存中排序。