4.5MongoDB实现地理位置索引

作者: 孔垂云 | 来源:发表于2017-05-21 01:06 被阅读1235次

MongoDB支持二维空间索引,使用空间索引,mongoDB支持一种特殊查询,如某地图网站上可以查找离你最近的咖啡厅,银行等信息。这个使用mongoDB的空间索引结合特殊的查询方法很容易实现。

现在常见的滴滴、膜拜、OFO等基于位置进行查询的场景都可以使用MongoDB的位置索引。

下面讲一下具体使用。

spring整合mongodb的信息参照4.2MongoDB和Spring整合

新建位置实体类Position.java

@Document(collection = "location")
public class Location {
    @Id
    private String id;//地点名称
    private double[] position;//位置信息

    public Location(String id, double lon, double lat) {
        this.id = id;
        double[] p = new double[]{lon, lat};
        this.position = p;
    }
//get set省略

这里面建了一个position的double二维数组,用于存储经纬度信息。
加了一个构造方法,用于初始化Location

位置查找的具体方法LocationRepository.java

@Repository
public class LocationRepository {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 按圆形查找
     *
     * @param point
     * @param maxDistance
     * @return
     */
    public List<Location> findCircleNear(Point point, double maxDistance) {
        Query query = new Query(Criteria.where("position").near(point).maxDistance(maxDistance / 111));
        return mongoTemplate.find(query, Location.class);
    }

    /**
     * 按方形查找
     *
     * @param lowerLeft
     * @param upperRight
     * @return
     */
    public List<Location> findBoxWithin(Point lowerLeft, Point upperRight) {
        Query query = new Query(Criteria.where("position").within(new Box(lowerLeft, upperRight)));
        return mongoTemplate.find(query, Location.class);
    }

这里面两个方法,一个是按照中心点范围查找,另一个是按照矩形范围查找,两个参数,一个是左下角位置,一个是右上角位置。

测试方法Test

@Test
    public void init() {
        // 等同db.location.ensureIndex( {position: "2d"} )
        mongoTemplate.indexOps(Location.class).ensureIndex(new GeospatialIndex("position"));
        // 初始化数据
        mongoTemplate.save(new Location("天安门", 116.4041602659, 39.9096215780));
        mongoTemplate.save(new Location("东单", 116.4244857287, 39.9144951360));
        mongoTemplate.save(new Location("王府井", 116.4177807251, 39.9175129885));
        mongoTemplate.save(new Location("西单", 116.3834863095, 39.9133467579));
        mongoTemplate.save(new Location("复兴门", 116.3631701881, 39.9129554253));
        mongoTemplate.save(new Location("复兴门", 116.3631701881, 39.9129554253));
        mongoTemplate.save(new Location("西四", 116.3799838526, 39.9299098531));
        mongoTemplate.save(new Location("菜市口", 116.3809950293, 39.8952009239));
        mongoTemplate.save(new Location("东四", 116.4239387439, 39.9306126797));
    }

初始化数据,这里拿天安门附近的一些数据作为例子。
在初始化之前,建立了一个GeospatialIndex索引,即位置索引

位置索引

这个位置索引在进行相关坐标查询时起到关键作用。可以试想一下,如果把上述信息存在普通的关系数据库中,想进行按中心点查询,该是一个多么复杂的操作,需要计算所有点到中心点的距离,然后判断距离是否满足范围。

/**
     * 查找天安门附近3公里的地点
     */
    @Test
    public void findCircleNearTest() {
        List<Location> locations = locationRepository.findCircleNear(new Point(116.4041602659, 39.9096215780), 3 / 111);
        locations.forEach(location -> {
            System.out.println(location.toString());
        });
    }

这里面116.4041602659, 39.9096215780是天安门的经纬度,3/111是3公里以内的数据。111是每一个经度代表的公里数(不懂的自补地理信息)。

查询结果如下:

按中心点查询
 /**
     * 查找左下角是菜市口,右上角是东四,这个方形区域内的所有点
     */
    @Test
    public void findBoxNearTest() {
        Point point1 = new Point(116.3809950293, 39.8952009239);
        Point point2 = new Point(116.4239387439, 39.9306126797);
        List<Location> locations = locationRepository.findBoxWithin(point1, point2);
        locations.forEach(location -> {
            System.out.println(location.toString());
        });
    }

查询结果如下:

矩形查找

基于MongoDB的位置信息查询性能非常非常高,在做位置信息查找时可以尝试使用MongoDB,会起到意想不到的效果。

源码下载

本工程详细源码

相关文章

  • 4.5MongoDB实现地理位置索引

    MongoDB支持二维空间索引,使用空间索引,mongoDB支持一种特殊查询,如某地图网站上可以查找离你最近的咖啡...

  • mongodb

    完全的索引支持 单键索引,多键索引,数组索引,全文索引,地理位置索引。

  • 地理位置索引-2d索引

    ``` > db.location.ensureIndex({"w":"2d"}) { "createdColle...

  • MongoDB实现地理位置查询

    Mongodb地理位置查询文档MongoDB支持地理位置索引,可以直接用于位置距离计算和查询。查询结果默认将会由近...

  • mysql索引

    mysql支持的索引 索引是在存储引擎层实现。而不是在mysql内实现 B-tree索引 index 普通索引 没...

  • MySql的索引实现

    MyISAM索引实现略InnoDB索引实现InnoDB的数据文件本身就是索引文件。MyISAM索引文件和数据文件是...

  • 地理位置geo处理之mongodb geo 索引

    Title: 地理位置geo处理之mongodb geo 索引Date: 2017-12-01 10:34Cate...

  • redis 地理位置信息

    redis 在3.2版本,集成了对于地理位置信息的支持,可以对数据进行地理位置索引建立。具体有下面6个命令。 1....

  • 超简单实现iOS列表的索引功能

    超简单实现iOS列表的索引功能 超简单实现iOS列表的索引功能

  • MySQL和ES的索引对比

    [toc] MySQL索引实现 在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,...

网友评论

  • needrunning:按照圆形和方形那两个基础方法是mongo自带的接口吗?
    needrunning:@孔垂云 感觉像是驱动自带的
    孔垂云:@needrunning 圆形是Query对象的near方法,方形是Query对象的within方法,这都是mongo自带的

本文标题:4.5MongoDB实现地理位置索引

本文链接:https://www.haomeiwen.com/subject/nnnpxxtx.html