SimpleDB obecnie nie oferuje żadnych wbudowanych operacji wyszukiwania przestrzennego, ale nie oznacza to, że nie można tego zrobić. Istnieje kilka metod implementacji wyszukiwania geoprzestrzennego w nie-geoprzestrzennie świadomych bazach danych, takich jak SimpleDB i wszystkie koncentrują się wokół idei korzystania z bazy danych w celu pobrania wstępnej pierwszej selekcji w oparciu o ramkę ograniczającą geoprzestrzenie, a następnie filtrowania zwróconych danych w aplikacji za pomocą dokładniejsze algorytmy, takie jak Haversine formula.
Ty mógł sklep szerokości i długości geograficznej jako (zero-wyściełane i znormalizowane) atrybutów numerycznych, a następnie wykonać podwójne zapytanie range (lat >= minLat and lat <= maxLat and lon >= minLat and lon <= maxLat
), ale ponieważ żaden z theese orzeczników są selektywne (każde orzeczenie odpowiada wiele elementów) nie jest idealny (patrz Tuning Queries).
Lepszym sposobem byłoby użycie GeoHashes.
Geohashes oferują właściwości jak arbitralnej precyzji, podobne przedrostki dla pobliskich stanowiskach oraz możliwość stopniowego usuwania znaków od końca kodu w celu zmniejszenia jego wielkości (i stopniowo utratę precyzji).
Jako praktyczny przykład, Geohash 6gkzwgjzn820 dekoduje do współrzędne -25,382708 i -49,265506, natomiast Geohash 6gkzwgjz będzie dekodowania do -25.383 -49.266 i, a jeśli weźmiemy podobną pozycję w tym samym regionie, takich jak -2,427 i -49,315, widzimy, że jest to zakodowane jako 6gkzmg1w (zauważ podobny przedrostek).
Od http://geohash.org/site/tips.html
ze swoimi pozycjami Rzecz jak GeoHashes można użyć operatora like
aby wyszukać obwiedni (where GeoHash like '6gkzmg1w%'
), ale ponieważ operator like
jest drogie (Comparison Operators) lepszym sposobem byłoby denormalize dane poprzez przechowywanie każdego prefiksu GeoHash (ile zależy od wymaganej precyzji wyszukiwania) jako oddzielnego atrybutu (GeoHash6 GeoHash8 itp.), a następnie użyj prostego predykatu równości (where Geohash8 = '6gkzmg1w'
).
Teraz na minus GeoHashów. Ponieważ nie możesz założyć, że GeoHash jest wyśrodkowany w twoim polu wyszukiwania, musisz również przeszukać wszystkie sąsiednie prefiksy. Proces jest doskonale opisany geohash-js
Geohash posiada tę właściwość, że ponieważ liczba cyfr zmniejsza (z prawej strony), dokładność spada. Ta właściwość może być używana do wyszukiwania ramek ograniczających, ponieważ punkty bliskie sobie nawzajem będą udostępniać podobne przedrostki Geohash.
Jednakże, ponieważ dany punkt może pojawić się na krawędzi danego Geohash Obwiednia, konieczne jest, aby wygenerować listę Geohash wartości w celu przeprowadzenia prawdziwej szukanie bliskości wokół punktu. Ponieważ algorytm Geohash stosuje się system numeracji bazowy 32 jest możliwe uzyskanie wartości Geohash wokół innej podanej wartość Geohash za pomocą prostego tabeli.
Tak więc, na przykład, 1600 Pennsylvania Avenue, Waszyngton postanawia: 38,897, -77,036
Stosując algorytm geohash, to szerokość i długość geograficzna jest przekształcany do: dqcjqcp84c6e
Prosty obwiedni wokół tego punktu może być opisany przez obcinania ten geohash do: dqcjqc
jednak „dqcjqcp84c6e” nie jest wyśrodkowany wewnątrz „dqcjqc” i szukają w „dqcjqc” może przegapić jakąś pożądaną Tarcza ts.
Zamiast tego możemy użyć matematycznych właściwości Geohash do szybko obliczyć sąsiadów "dqcjqc"; okazuje się, że są one: 'dqcjqf', 'dqcjqb', 'dqcjr1', 'dqcjq9', 'dqcjqd', 'dqcjr4', 'dqcjr0', 'dqcjq8'
To daje nam obwiedni wokół ' dqcjqcp84c6e "około 2 km x 1,5 km i pozwala na wyszukiwanie w bazie danych tylko 9 klawiszy: WYBIERZ * Z tabeli GDZIE LEWE (geohash, 6) IN (" dqcjqc ", " dqcjqf "," dqcjqb "," dqcjr1 ", "dqcjq9", "dqcjqd", "dqcjr4", "dqcjr0", "dqcjq8");
Przetłumaczony na zapytania SimpleDB Byłoby where GeoHash6 in('dqcjqc', 'dqcjqf', 'dqcjqb', 'dqcjr1', 'dqcjq9', 'dqcjqd', 'dqcjr4', 'dqcjr0', 'dqcjq8')
a potem zrobi swoje Haversine filtrowanie na wyniki w celu uzyskania tylko te elementy, które znajduje się w zasięgu promienia wyszukiwania.
Doskonała odpowiedź, dzięki za dyskusję na Geohashes – user293895