Geoprostorna podrška u ElasticSearch-u

1.Uvod

Elasticsearch je najpoznatiji po mogućnostima pretraživanja cijelog teksta, ali ima i potpunu geoprostornu podršku.

Više o postavljanju Elasticsearch-a i početku rada možemo pronaći u ovom prethodnom članku.

Pogledajmo kako možemo spremiti geo-podatke u Elasticsearch i kako možemo pretraživati ​​te podatke pomoću geo upita.

2. Geo tip podataka

Da bismo omogućili geo-upite, moramo ručno stvoriti mapiranje indeksa i izričito postaviti mapiranje polja.

Dinamično mapiranje neće raditi dok postavljate mapiranje za geotipove.

Elasticsearch nudi dva načina za predstavljanje geopodataka:

  1. Parovi zemljopisne širine i dužine koji koriste vrstu polja geo-točke
  2. Složeni oblik definiran u GeoJSON koristeći tip polja geo-oblika

Pogledajmo detaljnije svaku od gore navedenih kategorija:

2.1. Tip podataka Geo Point

Tip polja geo-točke prihvaća parove zemljopisne širine i dužine koji se mogu koristiti za:

  • Pronađite točke unutar određene udaljenosti od središnje točke
  • Pronađite točke unutar okvira ili poligona
  • Skupiti dokumente zemljopisno ili na udaljenosti od središnje točke
  • Poredajte dokumente po udaljenosti

Ispod je uzorak mapiranja polja za spremanje podataka o geotočki:

PUT / naziv_indeksa {"preslikavanja": {"TYPE_NAME": {"svojstva": {"lokacija": {"vrsta": "geo_točka"}}}}}}

Kao što vidimo iz gornjeg primjera, tip za mjesto polje je geo_point . Dakle, sada možemo pružiti par geografske širine i dužine u mjesto u polju lokacije.

2.2. Tip podataka Geo Shape

Za razliku od geo-točka, geo oblik pruža funkcionalnost za spremanje i pretraživanje složenih oblika poput poligona i pravokutnika. Geo oblik vrsta podataka mora se koristiti kada želimo pretraživati ​​dokumente koji sadrže oblike koji nisu geotočke.

Pogledajmo mapiranje za tip podataka o geo obliku:

PUT / naziv_indeksa {"preslikavanja": {"TYPE_NAME": {"svojstva": {"lokacija": {"vrsta": "geo_shape"}}}}}

Najnovije verzije Elasticsearch razlažu pruženi geo oblik u trokutastu mrežu. Prema službenoj dokumentaciji, ovo pruža gotovo savršenu prostornu razlučivost.

3. Različiti načini za spremanje podataka Geo točke

3.1. Objekt zemljopisne širine i dužine

STAVITE ime_indeksa / tip_indeksa / 1 {"location": {"lat": 23.02, "lon": 72.57}}

Evo, geo-točka mjesto je spremljeno kao objekt s zemljopisna širina i zemljopisna dužina kao ključevi.

3.2. Par zemljopisne širine i dužine

{"location": "23.02,72.57"}

Ovdje, mjesto izražava se kao par geografske širine i dužine u formatu običnog niza. Napominjemo, slijed geografske širine i dužine u formatu niza.

3.3. Geo Hash

{"location": "tsj4bys"}

Također možemo pružiti podatke o geotočki u obliku geoheša kao što je prikazano u gornjem primjeru. Pomoću mrežnog alata možemo pretvoriti geografsku širinu i dužinu u geoheš.

3.4. Zemljopisna širina

{"lokacija": [72,57, 23.02]}

Slijed zemljopisne širine i dužine obrnut je kada se zemljopisna širina i dužina daju kao niz. U početku se par zemljopisne širine i dužine koristio i u nizu i u nizu, no kasnije je obrnut kako bi odgovarao formatu koji koristi GeoJSON.

4. Različiti načini spremanja podataka o geoobliku

4.1. Točka

POST / indeks / tip {"location": {"type": "point", "koordinate": [72.57, 23.02]}}

Ovdje je vrsta geo oblika koji pokušavamo umetnuti a točka. Molimo pogledajte mjesto polje, imamo ugniježđeni objekt koji se sastoji od polja tip i koordinate. Ova meta-polja pomažu Elasticsearchu u identificiranju geo oblika i njegovih stvarnih podataka.

4.2. LineString

POST / indeks / tip {"location": {"type": "stringstring", "koordinate": [[77.57, 23.02], [77.59, 23.05]]}}

Evo, ubacujemo linijski niz geo oblik. Koordinate za linijski niz sastoji se od dvije točke tj. početne i krajnje točke. LineString geo oblik je vrlo koristan za slučajeve korištenja navigacije.

4.3. Poligon

POST / indeks / tip {"lokacija": {"vrsta": "poligon", "koordinate": [[[10,0, 0,0], [11,0, 0,0], [11,0, 1,0], [10,0, 1,0], [ 10,0, 0,0]]]}}

Evo, ubacujemo poligon geo oblik. Molimo pogledajte koordinate u gornjem primjeru, prvi i posljednji koordinate u poligonu uvijek se moraju podudarati, tj. sa zatvorenim poligonom.

Elasticsearch također podržava i druge GeoJSON strukture. Cjelovit popis ostalih podržanih formata nalazi se u nastavku:

  • MultiPoint
  • MultiLineString
  • MultiPoligon
  • Zbirka geometrije
  • Omotnica
  • Krug

Primjere gore podržanih formata možemo pronaći na službenim stranicama ES-a.

Za sve strukture, unutarnje tip i koordinate su obavezna polja. Također, sortiranje i pronalaženje polja geo oblika trenutno nisu moguća u Elasticsearchu zbog njihove složene strukture. Dakle, jedini način za dohvaćanje geopolja je iz izvornog polja.

5. Geografski upit ElasticSearch

Sad, kad znamo umetnuti dokumente koji sadrže geo oblike, zaronimo u dohvaćanje tih zapisa pomoću upita za geo oblik. Ali prije nego što započnemo koristiti Geo upite, trebat će nam sljedeće maven ovisnosti da podrže Java API za Geo upite:

 org.locationtech.spatial4j spatial4j 0.7 com.vividsolutions jts 1.13 xerces xercesImpl 

Gore navedene ovisnosti možemo potražiti i u spremištu Maven Central.

Elasticsearch podržava različite vrste geo upita, a oni su sljedeći:

5.1. Upit o geoobliku

To zahtijeva geo_oblik mapiranje.

Slično geo_oblik tip, geo_oblik koristi GeoJSON strukturu za ispitivanje dokumenata.

Ispod je primjer upita za dohvaćanje svih dokumenata koji padaju unutar date gornje lijeve i donje desne koordinate:

{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_shape": {"region": {"shape": {"type": "envelope "," koordinate ": [[75,00, 25,0], [80,1, 30,2]]}," relacija ":" unutar "}}}}}}

Ovdje, odnos određuje operatori prostornih odnosa koristi se u vrijeme pretraživanja.

Ispod je popis podržanih operatora:

  • INTERSECTS - (zadano) vraća sve dokumente čiji geo_oblik polje presijeca geometriju upita
  • RAZDJELITI - dohvaća sve dokumente čiji geo_oblik polje nema ništa zajedničko s geometrijom upita
  • UNUTAR - dobiva sve dokumente čiji geo_oblik polje je unutar geometrije upita
  • SADRŽI - vraća sve dokumente čiji geo_oblik polje sadrži geometriju upita

Slično tome, možemo postavljati upite pomoću različitih oblika GeoJSON-a.

Java kôd za gornji upit je kao u nastavku:

Koordinata topLeft = nova koordinata (74, 31.2); Koordinata bottomRight = nova koordinata (81.1, 24); GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery ("regija", novi EnvelopeBuilder (gornji lijevi, donji desni) .buildGeometry ()); qb.relation (ShapeRelation.INTERSECTS);

5.2. Upit za okvir za geografske granice

Upit Geo Bounding Box koristi se za dohvaćanje svih dokumenata na temelju mjesta točke. Ispod je primjer upita za ograničavajući okvir:

{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_bounding_box": {"location": {"bottom_left": [28.3, 30.5], " vrh_desno ": [31.8, 32.12]}}}}}}

Java kôd za upit iznad gornjeg okvira je kao u nastavku:

QueryBuilders .geoBoundingBoxQuery ("lokacija"). SetCorners (31.8, 30.5, 28.3, 32.12);

Upit Geo Bounding Box podržava slične formate kao i mi u geo_point vrsta podataka. Primjeri upita za podržane formate mogu se naći na službenim stranicama.

5.3. Upit za geografsku udaljenost

Upit za geografsku udaljenost koristi se za filtriranje svih dokumenata koji dolaze s navedenim rasponom točke.

Evo uzorka geo_dalja upit:

{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_distance": {"distance": "10miles", "location": [31.131,29.976 ]}}}}}

I evo Java koda za gornji upit:

QueryBuilders .geoDistanceQuery ("lokacija") .point (29.976, 31.131) .distance (10, DistanceUnit.MILES);

Slično geo_point, upit za geografsku udaljenost također podržava više formata za prosljeđivanje koordinata mjesta. Više detalja o podržanim formatima možete pronaći na službenim stranicama.

5.4. Geo Poligon Upit

Upit za filtriranje svih zapisa koji imaju točke koje spadaju u zadani poligon točaka.

Kratko ćemo pogledati uzorak upita:

{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_polygon": {"location": {"points": [{"lat": 22.733 , "lon": 68,859}, {"lat": 24,733, "lon": 68,859}, {"lat": 23, "lon": 70,859}]}}}}}}

I kod Java koda za ovaj upit:

Popis svih bodova = novi ArrayList (); allPoints.add (novi GeoPoint (22.733, 68.859)); allPoints.add (novi GeoPoint (24.733, 68.859)); allPoints.add (novi GeoPoint (23, 70.859)); QueryBuilders.geoPolygonQuery ("lokacija", allPoints);

Geo Polygon Query također podržava dolje navedene formate:

  • lat-long kao niz: [lon, lat]
  • lat dug kao niz: "lat, lon"
  • geo hash

geo_point vrsta podataka obavezna je za upotrebu ovog upita.

6. Zaključak

U ovom smo članku razgovarali o različitim mogućnostima mapiranja za indeksiranje geo podataka, tj geo_point i geo_oblik.

Također smo prošli različite načine skladištenja geo-podaci i na kraju, promatrali smo geo-upite i Java API za filtriranje rezultata pomoću geo-upita.

Kao i uvijek, kod je dostupan u ovom projektu GitHub.