1 of 18

Geohash i szukanie w pobliżu

Szymon Teżewski

@jasisz1

Przemysław Lewandowski

@haxoza

2 of 18

Jak to wygląda?

Sala 202

 

współrzędne: 52.219007, 21.012777

 

geohash: u3qcn4jjc0qn

3 of 18

4 of 18

U3

5 of 18

6 of 18

Nieparzyste geohashe

  • siatka 8x4
  • tyle samo bitów na długość i na szerokość

Parzyste geohashe

  • siatka 4x8
  • 1 bit więcej informacji o długości (kto zgadnie dlaczego?)

7 of 18

8 of 18

Magiczna właściwość

miejsca mają ten sam prefiks

=>

miejsca są w pobliżu

(znajdują się w tym samym prostokącie)

Niestety implikacja nie zachodzi w drugą stronę.

9 of 18

Niby blisko, a jednak...

10 of 18

A to i tak nic przy takich sytuacjach

11 of 18

Są sposoby na sposoby

12 of 18

A w Pythonie

Polecamy bibliotekę python-geohash

 

  • http://code.google.com/p/python-geohash/
  • prosta,
  • szybka,
  • jeszcze szybsza z rozszerzeniem w C,
  • dla japonofilów: napisał ją Japończyk Hiroaki Kawai, ze wsparciem dla używanego tam jpgrid �(podobne do geohasha)

13 of 18

python-geohash

>>> geohash.encode(42.6, -5.6)

'ezs42e44yx96'

 

>>> geohash.decode('ezs42') 

(42.60498046875, -5.60302734375

>>> geohash.expand('ezs42') 

['ezefr', 'ezs43', 'ezefx', 'ezs48', 'ezs49', 'ezefp', 'ezs40', 'ezs41', 'ezs42']

14 of 18

Przykład (niby-django)

import geohash

 

def near(qs, hash, prec=5):�    hashes = geohash.expand(hash[:prec])�    qfilter = Q()�    for h in hashes:�        qfilter = qfilter |

                  Q(geohash__startswith=h)�    return qs.filter(qfilter)

15 of 18

Z tego wyjdzie +/- zapytanie:

SELECT "place"."id", "place"."name",

"place"."geohash" WHERE

("place"."geohash" LIKE ezefr% OR

"place"."geohash" LIKE ezs43% OR

"place"."geohash" LIKE ezs40% OR

"place"."geohash" LIKE ezefp% OR

"place"."geohash" LIKE ezs41% OR

"place"."geohash" LIKE ezs48% OR

"place"."geohash" LIKE ezefx% OR

"place"."geohash" LIKE ezs49% OR

"place"."geohash" LIKE ezs42%

)

16 of 18

Inne rozwiązania

  • Umowna odległość d:

SELECT *

FROM Business

WHERE Lat > (position_lat - d) AND

      Lat < (position_lat + d) AND

      Lon > (position_lon - d) AND

      Lon < (position_lon + d);

Nie zadziała na Google App Engine.

  • GIS (PostGIS, GeoDjango)

17 of 18

Przydatne linki

18 of 18

Dziękujemy!