Baru-baru ini saya melakukan latihan dalam cuba membina apl sambil berpura-pura menjadi minimalis. Ini memerlukan saya dapat menapis mata gps tanpa menggunakan PostGIS rakan saya yang telah dicuba dan benar.
Saya mengambil lawatan pantas ke tiga cara paling popular untuk mengindeks data spatial : Geohash, H3 dan S2.
Kesemua 3 alat ini berfungsi dengan menghiris dunia ke dalam bentuk yang membahagikan kepada unit yang lebih kecil dan lebih kecil semasa anda mengezum masuk.
Cara terbaik untuk meneroka cara jenis indeks ini berfungsi ialah di https://geohash.softeng.co/. Semasa anda mengklik setiap sel, ia akan mengezum masuk dan menunjukkan kepada anda tahap yang lebih mendalam. Salah satu tempat kegemaran saya di dunia ialah di GeoHash ddk6p5
Menggunakan ini untuk "mengindeks" data GPS semudah menambah lajur teks untuk setiap peringkat yang anda minati. Contohnya, saya boleh membuat jadual seperti ini:
CREATE TABLE IF NOT EXISTS places ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, latitude REAL, longitude REAL, geohash_level_2 TEXT, geohash_level_4 TEXT ); INSERT INTO places (name,latitude,longitude,geohash_level_2,geohash_level_4) VALUES('mt shavano', 38.618840, -106.239364, '9w', '9wu7'); INSERT INTO places (name,latitude,longitude,geohash_level_2,geohash_level_4) VALUES('blanca peak', 37.578047, -105.485796, '9w', '9wsv'); INSERT INTO places (name,latitude,longitude,geohash_level_2,geohash_level_4) VALUES('mt princeton', 38.749148, -106.242578, '9w', '9wuk'); INSERT INTO places (name,latitude,longitude,geohash_level_2,geohash_level_4) VALUES('la soufriere', 13.336299, -61.177146, 'dd', 'ddk7');
Sqlime ialah tempat yang baik untuk mencuba pertanyaan ini.
Kemudian untuk mencari tempat di selatan Colorado, saya akan mencari cincang yang meliputi bahagian peta itu iaitu '9w':
SELECT * FROM places WHERE geohash_level_2 = '9w';
Untuk mencari tempat di selatan Caribbean saya boleh menggunakan:
SELECT * FROM places WHERE geohash_level_2 = 'dd';
Pendekatan ini memerlukan beberapa perancangan awal tentang tahap indeks yang anda perlu simpan dalam pangkalan data anda. Jika tidak, ia berfungsi dengan baik untuk aplikasi mudah yang anda perlu mencari dengan cepat objek mana yang ditemui di kawasan tertentu atau port pandangan peta.
Mempunyai pangkalan data yang menyokong pertanyaan LIKE boleh membantu mengurangkan penggunaan berbilang lajur. Juga ambil perhatian bahawa nombor sel H3 tidak bertindih dengan sempurna jadi pertanyaan jenis "bermula dengan" tidak akan berfungsi dengan H3.
Akhir sekali, ciri yang kemas bagi indeks ini ialah nombor sel akan menjadi topik acara masa nyata yang hebat. Jadi, dalam contoh saya di atas, saya boleh mencipta topik acara yang dipanggil '9w' untuk colorado selatan. Kemudian apabila tempat baharu ditambah, saya akan mengeluarkan acara dalam topik '9w' untuk setiap tempat baharu.
Berikut ialah beberapa contoh kod JavaScript (deno) untuk setiap jenis indeks ini:
Perhatikan bahawa output GeoJSON boleh dilihat di sini : https://geojson.io/
import { geocoordinateToGeohash } from 'npm:geocoordinate-to-geohash' import { geohashToPolygonFeature } from 'npm:geohash-to-geojson' import geohash from 'npm:ngeohash' const lat = 38.618840 const lng = -106.239364 const hash2 = geohash.encode(lat, lng, 2) console.log('mt shavano hash at level 2', hash2) const feat2 = geohashToPolygonFeature(hash2) console.log('mt shavano hash at level 2 bounds', JSON.stringify(feat2)) // About a city block in size in CO (size changes as you head towards poles) const hash7 = geohash.encode(lat, lng, 7) console.log('mt shavano hash at level 4', hash7) const feat7 = geohashToPolygonFeature(hash7) console.log('mt shavano hash at level 4 bounds', JSON.stringify(feat7))
import h3 from 'npm:h3-js' import geojson2h3 from "npm:geojson2h3" const lat = 38.618840 const lng = -106.239364 // Level 2 (~1/3 Colorado Size) const h3IndexL2 = h3.latLngToCell(lat, lng, 2); console.log('mt shavano cell at level 2', h3IndexL2) const featureL2 = geojson2h3.h3ToFeature(h3IndexL2) console.log('mt shavano cell at level 2 bounds', JSON.stringify(featureL2)) // Level 4 (~City of Salida Size) const h3IndexL4 = h3.latLngToCell(lat, lng, 4); console.log('mt shavano cell at level 4', h3IndexL4) const featureL4 = geojson2h3.h3ToFeature(h3IndexL4) console.log('mt shavano cell at level 4 bounds', JSON.stringify(featureL4))
// This might be a better choice : https://www.npmjs.com/package/@radarlabs/s2 import s2 from 'npm:s2-geometry' const S2 = s2.S2 const lat = 38.618840 const lng = -106.239364 const key2 = S2.latLngToKey(lat, lng, 2) const id2 = S2.keyToId(key2) const feature2 = cellCornersToFeatureCollection(lat, lng, 2) console.log('mt shavano key at level 2', key2) console.log('mt shavano cell id at level 2', id2) console.log('mt shavano cell at level 2 corners', JSON.stringify(feature2)) const key4 = S2.latLngToKey(lat, lng, 4) const id4 = S2.keyToId(key4) const feature4 = cellCornersToFeatureCollection(lat, lng, 4) console.log('mt shavano key at level 4', key4) console.log('mt shavano cell id at level 4', id4) console.log('mt shavano cell at level 4 corners', JSON.stringify(feature4)) function cellCornersToFeatureCollection(lat, lng, level) { const ll = S2.L.LatLng(lat, lng) const cell = S2.S2Cell.FromLatLng(ll, level) const corners = cell.getCornerLatLngs() const coordinates = corners.map((pair) => { return [pair.lng, pair.lat] }) return { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [coordinates] }, "properties": {} } ] } }
Atas ialah kandungan terperinci Pensampel Pengindeksan Geospatial. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!