4.5MongoDB實現(xiàn)地理位置索引

MongoDB支持二維空間索引,使用空間索引,mongoDB支持一種特殊查詢,如某地圖網(wǎng)站上可以查找離你最近的咖啡廳,銀行等信息。這個使用mongoDB的空間索引結(jié)合特殊的查詢方法很容易實現(xiàn)择份。

現(xiàn)在常見的滴滴歌憨、膜拜娘赴、OFO等基于位置進(jìn)行查詢的場景都可以使用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二維數(shù)組砾隅,用于存儲經(jīng)緯度信息俱济。
加了一個構(gòu)造方法嘶是,用于初始化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);
    }

這里面兩個方法蛛碌,一個是按照中心點范圍查找聂喇,另一個是按照矩形范圍查找,兩個參數(shù)蔚携,一個是左下角位置希太,一個是右上角位置。

測試方法Test

@Test
    public void init() {
        // 等同db.location.ensureIndex( {position: "2d"} )
        mongoTemplate.indexOps(Location.class).ensureIndex(new GeospatialIndex("position"));
        // 初始化數(shù)據(jù)
        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("復(fù)興門", 116.3631701881, 39.9129554253));
        mongoTemplate.save(new Location("復(fù)興門", 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));
    }

初始化數(shù)據(jù)酝蜒,這里拿天安門附近的一些數(shù)據(jù)作為例子誊辉。
在初始化之前,建立了一個GeospatialIndex索引亡脑,即位置索引

位置索引

這個位置索引在進(jìn)行相關(guān)坐標(biāo)查詢時起到關(guān)鍵作用堕澄。可以試想一下霉咨,如果把上述信息存在普通的關(guān)系數(shù)據(jù)庫中蛙紫,想進(jìn)行按中心點查詢,該是一個多么復(fù)雜的操作躯护,需要計算所有點到中心點的距離,然后判斷距離是否滿足范圍丽涩。

/**
     * 查找天安門附近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是天安門的經(jīng)緯度,3/111是3公里以內(nèi)的數(shù)據(jù)棺滞。111是每一個經(jīng)度代表的公里數(shù)(不懂的自補(bǔ)地理信息)。

查詢結(jié)果如下:

按中心點查詢
 /**
     * 查找左下角是菜市口矢渊,右上角是東四继准,這個方形區(qū)域內(nèi)的所有點
     */
    @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());
        });
    }

查詢結(jié)果如下:

矩形查找

基于MongoDB的位置信息查詢性能非常非常高,在做位置信息查找時可以嘗試使用MongoDB矮男,會起到意想不到的效果移必。

源碼下載

本工程詳細(xì)源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市毡鉴,隨后出現(xiàn)的幾起案子崔泵,更是在濱河造成了極大的恐慌秒赤,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件憎瘸,死亡現(xiàn)場離奇詭異入篮,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)幌甘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門潮售,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锅风,你說我怎么就攤上這事酥诽。” “怎么了皱埠?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵肮帐,是天一觀的道長。 經(jīng)常有香客問我漱逸,道長泪姨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任饰抒,我火速辦了婚禮肮砾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘袋坑。我一直安慰自己仗处,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布枣宫。 她就那樣靜靜地躺著婆誓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪也颤。 梳的紋絲不亂的頭發(fā)上洋幻,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機(jī)與錄音翅娶,去河邊找鬼文留。 笑死,一個胖子當(dāng)著我的面吹牛竭沫,可吹牛的內(nèi)容都是我干的燥翅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蜕提,長吁一口氣:“原來是場噩夢啊……” “哼森书!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤凛膏,失蹤者是張志新(化名)和其女友劉穎杨名,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體译柏,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡镣煮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鄙麦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片典唇。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖胯府,靈堂內(nèi)的尸體忽然破棺而出介衔,到底是詐尸還是另有隱情,我是刑警寧澤骂因,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布炎咖,位于F島的核電站,受9級特大地震影響寒波,放射性物質(zhì)發(fā)生泄漏乘盼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一俄烁、第九天 我趴在偏房一處隱蔽的房頂上張望绸栅。 院中可真熱鬧,春花似錦页屠、人聲如沸粹胯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽风纠。三九已至,卻和暖如春牢贸,著一層夾襖步出監(jiān)牢的瞬間竹观,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工潜索, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留臭增,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓帮辟,卻偏偏與公主長得像速址,于是被迫代替她去往敵國和親玩焰。 傳聞我的和親對象是個殘疾皇子由驹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容