1. 程式人生 > >再提LBS經緯度搜索和距離排序,求更優方案

再提LBS經緯度搜索和距離排序,求更優方案

  地理位置索引支援是MongoDB的一大亮點,這也是全球最流行的LBS服務foursquare 選擇MongoDB的原因之一。我們知道,通常的資料庫索引結構是B+ Tree,如何將地理位置轉化為可建立B+Tree的形式,下文將為你描述。

Advertisement

  首先假設我們將需要索引的整個地圖分成16×16的方格,如下圖(左下角為座標0,0 右上角為座標16,16):

  單純的[x,y]的資料是無法建立索引的,所以MongoDB在建立索引的時候,會根據相應欄位的座標計算一個可以用來做索引的hash值,這個值叫做geohash,下面我們以地圖上座標為[4,6]的點(圖中紅叉位置)為例。

  我們第一步將整個地圖分成等大小的四塊,如下圖:

  劃分成四塊後我們可以定義這四塊的值,如下(左下為00,左上為01,右下為10,右上為11):

0111
0010

  這樣[4,6]點的geohash值目前為 00

  然後再將四個小塊每一塊進行切割,如下:

  這時[4,6]點位於右上區域,右上的值為11,這樣[4,6]點的geohash值變為:0011

  繼續往下做兩次切分:

  最終得到[4,6]點的geohash值為:00110100

  這樣我們用這個值來做索引,則地圖上點相近的點就可以轉化成有相同字首的geohash值了。

  我們可以看到,這個geohash值的精確度是與劃分地圖的次數成正比的,上例對地圖劃分了四次。而MongoDB預設是進行26次劃分,這個值在建立索引時是可控的。具體建立二維地理位置索引的命令如下:

  db.map.ensureIndex({point : "2d"}, {min : 0, max : 16, bits : 4})

  其中的bits引數就是劃分幾次,預設為26次。

原文出處:http://blog.nosqlfan.com/html/1811.html