Mongodb 地理位置索引

MongoDB地理空间索引详解
本文详细介绍了MongoDB中的地理空间索引功能,包括如何创建2D索引,使用$near和$within等查询操作符进行基于位置的查询,以及如何结合复合索引进行更复杂的筛选。

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.youkuaiyun.com/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

Mongodb 地理位置索引

Geospatial Indexing

     MongoDB支持二维空间索引,这是设计时考虑到基于位置的查询。例如“找到离目标位置最近的N条记录”。可以有效地作为附加条件过滤。

     如果需要使用这种索引,应确定对象中存储的字段是子对象或数组,前两个元素为X,Y坐标(或者Y,X坐标,保持一致即可。it might be advisible to use order-preserving dictionaries/hashes in your client code, to ensure consistency),一些例子:

 

Mongo代码  

{ loc : [ 50 , 30 ] }  

{ loc : { x : 50 , y : 30 } }  

{ loc : { foo : 50 , y : 30 } }  

{ loc : { lat : 40.739037, long: 73.992964 } }  

 

   Creating the Index

 

Mongo代码  

db.places.ensureIndex( { loc : "2d" } )     //应该是固定格式  

 

     默认的,Mongo假设你索引的是经度/维度,因此配置了一个从-180到180的取值范围,如果你想索引更多,可以指定该参数:

 

Mongo代码  

db.places.ensureIndex( { loc : "2d" } , { min : -500 , max : 500 } )  

 

     上面的代码将衡量索引保证存入的值在-500到500的范围之内。一般来说geo索引仅限于正方形以内且不包括边界以以外的范围,不能再边界上插入值,比如使用上面的代码,点(-500,-500)是不能被插入的。

 

     目前为止,每个Collection只能建立一个geo索引

 

    Querying

      该索引可以被用来精确匹配:

 

Mongo代码  

db.places.find( { loc : [50,50] } )  

 

     对于geo索引来说,更重要的是一个查询可以找到目标点附近的点,不必要精确匹配。

 

Mongo代码  

db.places.find( { loc : { $near : [50,50] } } )  

 

     上面的一句将按离目标点(50,50)距离最近的100个点(距离倒序排列),如果想指定返回的结果个数,可以使用limit()函数,若不指定,默认是返回100个。

 

Mongo代码  

db.places.find( { loc : { $near : [50,50] } } ).limit(20)  

 

    Compound Indexes

      Mongo空间索引可选的支持第二字段索引.如果想用坐标和其他属性同事作为条件查询,把这个属性也一同索引,其他属性带注释性的加入索引中可使过滤更快。

 

Mongo代码  

db.places.ensureIndex( { location : "2d" , category : 1 } );  

db.places.find( { location : { $near : [50,50] }, category : 'coffee' } );  

 

    geoNear Command

      虽然find()语法为查询的首选,Mongo也提供来了 geoNear 命令来执行相似的函数。geoNear命令有一个额外的好处是结果中返回距离目标点的距离,以及一些利于排除故障的信息。

Mongo代码  

> db.runCommand( { geoNear : "places" , near : [50,50], num : 10 } );  

> db.runCommand({geoNear:"asdf", near:[50,50]})  

{  

        "ns" : "test.places",  

        "near" : "1100110000001111110000001111110000001111110000001111",  

        "results" : [  

                {  

                        "dis" : 69.29646421910687,  

                        "obj" : {  

                                "_id" : ObjectId("4b8bd6b93b83c574d8760280"),  

                                "y" : [  

                                        1,  

                                        1  

                                ],  

                                "category" : "Coffee"  

                        }  

                },  

                {  

                        "dis" : 69.29646421910687,  

                        "obj" : {  

                                "_id" : ObjectId("4b8bd6b03b83c574d876027f"),  

                                "y" : [  

                                        1,  

                                        1  

                                ]  

                        }  

                }  

        ],  

        "stats" : {  

                "time" : 0,  

                "btreelocs" : 1,  

                "btreelocs" : 1,  

                "nscanned" : 2,  

                "nscanned" : 2,  

                "objectsLoaded" : 2,  

                "objectsLoaded" : 2,  

                "avgDistance" : 69.29646421910687  

        },  

        "ok" : 1  

}  

 

     上面的命令将返回10条距离点(50,50)最近的记录,loc字段由该collection的空间索引自动检测后决定。

     如果你想添加一条过滤条件,可以这样:

Mongo代码  

> db.runCommand( { geoNear : "places" , near : [ 50 , 50 ], num : 10,  

... query : { type : "museum" } } );  

 

    Bounds Queries

    v1.3.4版本以上

     $within 参数可以代替$near来查找一个形状之内结果。同时,也支持$box(矩形)和$center(圆环)

    想要查找一个一个矩形之内所有的点,必须制定该矩形的左下角和右上角坐标:

Mongo代码  

> box = [[40, 40], [60, 60]]  

> db.places.find({"loc" : {"$within" : {"$box" : box}}})  

 

更多信息请参考

http://www.mongodb.org/display/DOCS/Geospatial+Indexing 


Geospatial Query Operators

Operators

Query Selectors

NameDescription
$geoWithinSelects geometries within a bounding GeoJSON geometry.
$geoIntersectsSelects geometries that intersect with a GeoJSON geometry.
$nearReturns geospatial objects in proximity to a point.
$nearSphereReturns geospatial objects in proximity to a point on a sphere.

Geometry Specifiers

NameDescription
$geometrySpecifies a geometry in GeoJSON format to geospatial query operators.
$maxDistanceSpecifies a distance to limit the results of $near and $nearSphere queries.
$centerSpecifies a circle using legacy coordinate pairs to $geoWithin queries when using planar geometry.
$centerSphereSpecifies a circle using either legacy coordinate pairs or GeoJSON format for $geoWithin queries when using spherical geometry.
$boxSpecifies a rectangular box using legacy coordinate pairs for $geoWithin queries.
$polygonSpecifies a polygon to using legacy coordinate pairs for $geoWithin queries.
$uniqueDocsModifies a $geoWithin and $near queries to ensure that even if a document matches the query multiple times, the query returns the document once.

Geospatial Query Compatibility

While numerous combinations of query operators are possible, the following table shows the recommended operators for different types of queries. The table uses the $geoWithin$geoIntersects and $near operators.

Query DocumentGeometry of the Query ConditionSurface Type for Query CalculationUnits for Query CalculationSupported by this Index
Returns points, lines and polygons    
{ $geoWithin : {  $geometry : <GeoJSON Polygon>} }
polygonspheremeters2dsphere
{ $geoIntersects : {  $geometry : <GeoJSON>} }
point, line or polygonspheremeters2dsphere
{ $near : {  $geometry : <GeoJSON Point>,  $maxDistance : d} }
pointspheremeters

2dsphere

The index is required.

Returns points only    
{ $geoWithin : {  $box : [[x1, y1], [x2, y2]]} }
rectangleflatflat units2d
{ $geoWithin : {  $polygon : [[x1, y1],              [x1, y2],              [x2, y2],              [x2, y1]]} }
polygonflatflat units2d
{ $geoWithin : {  $center : [[x1, y1], r],} }
circular regionflatflat units2d
{ $geoWithin : {  $centerSphere :    [[x, y], radius]} }
circular regionsphereradians

2d

2dsphere

{ $near : [x1, y1],  $maxDistance : d}

           

给我老师的人工智能教程打call!http://blog.youkuaiyun.com/jiangjunshow
这里写图片描述
<think>好的,我现在需要帮用户解决关于MongoDB地理位置索引的问题。首先,我要确认用户的需求。用户问的是“如何在MongoDB中创建和使用地理位置索引”,需要教程、创建方法和示例。根据提供的引用内容,特别是引用[3]和[4],我需要整理相关信息。 首先,我得回忆MongoDB地理位置索引类型。通常有两种:2d和2dsphere。2d适用于平面坐标,而2dsphere用于地理空间坐标如经纬度。用户可能需要知道这两种的区别和适用场景。 接下来,创建索引的方法。根据引用中的示例,比如引用[2]展示了文本索引的创建,类似地,地理位置索引应该使用createIndex方法。例如,对于2dsphere索引,命令应该是db.collection.createIndex({字段名: "2dsphere"})。需要确保用户的数据结构正确,比如字段是GeoJSON格式或者传统坐标对。 然后,使用场景和查询操作。引用[4]提到了$geoWithin和$box的示例,用户可能需要知道其他操作符如$near、$geoNear等。需要解释每个操作符的作用,并提供示例代码。 另外,注意事项也很重要。比如创建索引前需要数据格式正确,2dsphere需要GeoJSON,而2d则使用传统坐标。还要提到性能优化,索引对写入的影响,以及地理空间查询的限制。 现在,检查提供的引用材料。引用[3]提到了索引管理的基本概念,引用[4]给出了一个查询示例。需要确保回答中包含创建步骤、示例代码和不同查询方法的应用。 可能需要分步骤说明:创建前的数据准备、创建索引的命令、不同查询操作符的使用,以及示例。同时,要引用提供的参考资料,比如引用[4]中的示例,并在末尾添加引用标识。 最后,生成相关问题,比如如何优化地理位置查询性能,或者如何处理不同类型的地理数据。这样用户可以有进一步的学习方向。</think>### MongoDB地理位置索引使用教程 #### 一、数据准备 创建地理位置索引前,文档中需包含地理坐标字段,支持两种格式: 1. **GeoJSON格式**(推荐):例如`{ type: "Point", coordinates: [经度, 纬度] }` 2. **传统坐标对**:例如`[经度, 纬度]`,但需注意查询时使用`$box`等操作符需严格匹配格式[^4] #### 二、创建索引 MongoDB提供两种地理位置索引类型: 1. **2dsphere索引**(地球球面) ```javascript db.shop.createIndex({ loc: "2dsphere" }) // 创建基于GeoJSON的索引 ``` 2. **2d索引**(平面坐标系) ```javascript db.shop.createIndex({ loc: "2d" }) // 传统坐标对索引 ``` #### 三、查询操作 通过`$geoWithin`、`$near`等操作符实现空间查询: 1. **矩形范围查询**(使用2d索引) ```javascript db.shop.find({ loc: { "$geoWithin": { "$box": [[9,9], [11,11]] // 左下角坐标 → 右上角坐标 } } }) // ``` 2. **圆形范围查询**(2dsphere索引) ```javascript db.shop.find({ loc: { $geoWithin: { $centerSphere: [[120.67, 31.32], 0.01] // 中心坐标 + 半径(弧度) } } }) ``` 3. **邻近点查询** ```javascript db.shop.find({ loc: { $near: { $geometry: { type: "Point", coordinates: [121.47, 31.23] }, $maxDistance: 1000 // 最大距离(米) } } }) ``` #### 四、最佳实践 1. **数据标准化**:优先使用GeoJSON格式,便于支持更复杂的空间计算 2. **复合索引**:对经常组合查询的字段(如位置+品类)创建复合索引 ```javascript db.shop.createIndex({ loc: "2dsphere", category: 1 }) ``` 3. **性能监控**:通过`explain()`分析查询执行计划
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值