Saya mencari untuk mengoptimalkan waktu kedekatan geo titik pencarian.
Input saya adalah lat, titik lng dan saya sedang mencari pada set lokasi yang telah dikomputasi ke n titik terdekat.
Saya tidak peduli berapa banyak waktu / ruang pembangunan indeks prekomputasi lokasi akan mengambil tapi saya peduli pertanyaan akan sangat cepat.
Saya sedang berpikir tentang menggunakan geohash sebagai kunci pencarian, di mana saya pertama kali akan memeriksa apakah saya mendapatkan hasil untuk karakter X kunci dan kemudian terus memangkas karakter dari akhir kunci sampai saya mulai melihat hasil.
Untuk pemahaman saya (sangat jarang untuk saat ini) tentang teknik indeks geo, pendekatan ini harus dapat menghasilkan hasil tercepat (dalam hal waktu permintaan) dibandingkan dengan semua implementasi yang diketahui lainnya (seperti R Tree dan rekan).
Jawaban:
Anda pasti bisa. Dan itu bisa sangat cepat. (Bit komputasi intensif juga dapat didistribusikan)
Ada beberapa cara, tetapi satu cara yang telah saya kerjakan adalah dengan menggunakan daftar urutan geohash berbasis integer, dan menemukan semua rentang geohash tetangga terdekat untuk resolusi geohash tertentu (resolusi mendekati
distance
kriteria Anda ), dan kemudian menanyakan rentang geohash tersebut untuk mendapatkan daftar poin terdekat. Saya menggunakan redis dan nodejs (mis. Javascript) untuk ini. Redis sangat cepat dan dapat mengambil rentang yang dipesan dengan sangat cepat, tetapi itu tidak dapat melakukan banyak hal manipulasi pengindeksan kueri yang dapat dilakukan oleh database SQL.Metodenya diuraikan di sini: https://github.com/yinqiwen/ardb/wiki/Spatial-Index
Tetapi intinya adalah (untuk memparafrasekan tautannya):
Anda dapat lebih mengoptimalkan (kecepatan bijaksana) ini dengan:
Anda selanjutnya dapat meningkatkan akurasi dengan menggunakan fungsi tipe circle distance / haversine pada hasil yang dikembalikan jika Anda sangat peduli dengan presisi.
Berikut teknik serupa menggunakan geohash base32 biasa dan kueri SQL alih-alih redis: https://github.com/davetroy/geohash-js
Saya tidak bermaksud menyambungkan hal saya sendiri, tetapi saya telah menulis modul untuk nodejs & redis yang membuat ini sangat mudah diimplementasikan. Lihat kode jika Anda ingin: https://github.com/arjunmehta/node-georedis
sumber
Pertanyaannya bisa dibaca dalam beberapa cara. Saya menafsirkannya berarti Anda memiliki sejumlah besar poin dan Anda berniat untuk menyelidikinya berulang kali dengan titik arbitrer, diberikan sebagai pasangan koordinat, dan berharap untuk mendapatkan n poin terdekat ke penyelidikan, dengan n diperbaiki sebelumnya. (Pada prinsipnya, jika n akan bervariasi, Anda dapat mengatur struktur data untuk setiap kemungkinan n dan memilihnya dalam waktu O (1) dengan setiap probe: ini bisa memakan waktu setup yang sangat lama dan membutuhkan banyak RAM, tetapi kami diberitahu untuk mengabaikan masalah tersebut.)
Buatlah diagram urutan-n Voronoi dari semua poin. Ini mempartisi pesawat menjadi wilayah yang terhubung, yang masing-masing memiliki n tetangga yang sama. Ini mengurangi situasi menjadi masalah point-in-polygon, yang memiliki banyak solusi efisien.
Menggunakan struktur data vektor untuk diagram Voronoi, pencarian titik-dalam-poligon akan memakan waktu O (log (n)) waktu. Untuk tujuan praktis, Anda dapat membuat O (1) ini dengan koefisien implisit yang sangat kecil hanya dengan membuat versi diagram raster. Nilai sel dalam raster dapat berupa (i) penunjuk ke daftar n titik terdekat atau (ii) indikasi bahwa sel ini mengangkangi dua atau lebih daerah dalam diagram. Tes untuk titik arbitrer di (x, y) menjadi:
Untuk mencapai kinerja O (1), mesh raster harus cukup baik sehingga titik probe yang relatif sedikit akan jatuh dalam sel yang mengangkangi beberapa wilayah Voronoi. Ini selalu dapat dicapai, dengan potensi biaya yang besar dalam penyimpanan untuk grid.
sumber
Saya menggunakan geohash untuk hal ini. Alasan saya adalah karena saya perlu menerapkan pencarian kedekatan menggunakan sistem informasi gaya piramida .. di mana geohash dengan tingkat presisi 8 adalah 'basis' dan membentuk total baru untuk geohash dari ketepatan ke-7 .. dan seterusnya dan seterusnya . Total ini adalah area, jenis penutup tanah, dll. Itu adalah cara yang sangat mewah untuk melakukan beberapa hal yang sangat mewah.
Jadi geohash level 8 akan berisi informasi seperti:
jenis: rumput acre: 1.23
dan 7, 6 .. dll. akan berisi informasi seperti:
grass_types: 123 acre: 6502
Ini selalu dibangun dari presisi terendah. Ini memungkinkan saya untuk melakukan segala macam statistik yang menyenangkan dengan sangat cepat. Saya juga dapat menetapkan referensi geometri untuk setiap referensi geohash menggunakan GeoJSON.
Saya dapat menulis beberapa fungsi untuk menemukan geohash terbesar yang membentuk viewport saya saat ini dan kemudian menggunakannya untuk menemukan geohash dengan presisi terbesar kedua di dalam viewport. Ini dapat dengan mudah diperluas ke kueri rentang terindeks di mana saya akan meminta minimum '86ssaaaa' dan maksimum '86sszzzz' untuk presisi apa pun yang saya inginkan.
Saya melakukan ini menggunakan MongoDB.
sumber
Memperbarui untuk tahun 2018-an, dan beberapa dana matematika atau sumber bersejarah Geohash:
inspirasi untuk Geohash adalah interlave sederhana dari angka-angka biner , mungkin suatu optimasi dari algoritma naif yang interleave digit desimal, seperti dari C-square .
pertautan biner menghasilkan strategi indeks kurva Z-order secara alami, penemu Geohash tidak mulai "mencari kurva fraktal terbaik" ... Tapi yang pasti, optimasi desain ini, kurva fraktal yang lebih baik, dimungkinkan (!).
Gunakan Perpustakaan Geometri S2
Pendekatan S2-geometri lebih baik daripada Geohash karena menggunakan topologi bola dunia (kubus), gunakan proyeksi opsional (jadi semua sel memiliki bentuk yang hampir sama dan dekat), dan karena pengindeksan dengan kurva Hilbert lebih baik daripada Z- urutan-kurva :
Sekarang ini adalah perpustakaan yang gratis dan efisien, lihat https://s2geometry.io
PS: ada juga versi disederhanakan yang tidak resmi (baik) seperti NodeJS
s2-geometry
, dan banyak "taman bermain", tambahan dan demo, seperti s2.sidewalklabs.com .sumber
Saya akan merekomendasikan menggunakan kueri GEORADIUS di redis.
Dorong data yang terbagi-bagi oleh level geohash yang paling cocok menggunakan panggilan GEOADD.
Juga, lihat ini -> ProximityHash .
ProximityHash menghasilkan satu set geohash yang mencakup area melingkar, mengingat koordinat pusat dan radius. Ia juga memiliki opsi tambahan untuk menggunakan GeoRaptor yang menciptakan kombinasi geohash terbaik di berbagai tingkatan untuk mewakili lingkaran, mulai dari tingkat tertinggi dan iterasi hingga campuran optimal diseduh. Akurasi hasil tetap sama dengan tingkat geohash awal, tetapi ukuran data berkurang secara signifikan, sehingga meningkatkan kecepatan dan kinerja.
sumber