Geospatial Support i ElasticSearch
1.Introduksjon
Elasticsearch er best kjent for sine muligheter for fulltekstsøk, men det har også full geospatial støtte.
Vi kan finne mer om hvordan du setter opp Elasticsearch og kommer i gang i denne forrige artikkelen.
La oss ta en titt på hvordan vi kan lagre geodata i Elasticsearch og hvordan vi kan søke i disse dataene ved hjelp av geografiske spørsmål.
2. Geodatatype
For å aktivere geosøk, må vi opprette kartleggingen av indeksen manuelt og eksplisitt angi feltkartleggingen.
Dynamisk kartlegging fungerer ikke mens du angir kartlegging for geotyper.
Elasticsearch tilbyr to måter å representere geodata på:
- Par på breddegrad og lengdegrad ved hjelp av geo-punkt felttype
- Kompleks form definert i GeoJSON ved hjelp av geo-form felttype
La oss se nærmere på hver av kategoriene ovenfor:
2.1. Geo Point Data Type
Geo-point felttype aksepterer breddegrad / lengdegradspar som kan brukes til å:
- Finn punkter innenfor en viss avstand fra sentralt punkt
- Finn punkter i en boks eller en polygon
- Samle dokumenter geografisk eller etter avstand fra det sentrale punktet
- Sorter dokumenter etter avstand
Nedenfor er eksempelkartlegging for feltet for å lagre data om geo-punkt:
PUT / index_name {"mappings": {"TYPE_NAME": {"properties": {"location": {"type": "geo_point"}}}}
Som vi kan se fra eksemplet ovenfor, type til plassering feltet er geo_point . Dermed kan vi nå gi breddegrad / lengdegradspar i plassering i plasseringsfeltet.
2.2. Geo Shape Datatype
I motsetning til geo-point, geo form gir funksjonaliteten til å lagre og søke i komplekse former som polygon og rektangel. Geo form datatypen må brukes når vi vil søke i dokumenter som inneholder andre former enn geo-punkter.
La oss ta en titt på kartlegging for datatype for geografisk form:
PUT / index_name {"mappings": {"TYPE_NAME": {"properties": {"location": {"type": "geo_shape"}}}}}
Nylige versjoner av Elasticsearch bryter ned den oppgitte geoformen i et trekantet nett. I følge den offisielle dokumentasjonen gir dette nesten perfekt romlig oppløsning.
3. Ulike måter å lagre Geo Point-data på
3.1. Breddegrad lengdegrad objekt
PUT index_name / index_type / 1 {"location": {"lat": 23.02, "lon": 72.57}}
Her, geo-point plassering blir lagret som et objekt med breddegrad og lengdegrad som nøkler.
3.2. Breddegrad par
{"location": "23.02,72.57"}
Her, plassering uttrykkes som et breddegrad / lengdegradspar i vanlig strengformat. Vær oppmerksom på sekvensen for bredde og lengdegrad i strengformat.
3.3. Geo Hash
{"location": "tsj4bys"}
Vi kan også gi geo-punktdata i form av geo-hash som vist i eksemplet ovenfor. Vi kan bruke det elektroniske verktøyet til å konvertere breddegrad og geo-hash.
3.4. Lengdegrad breddegrad
{"location": [72.57, 23.02]}
Sekvensen for breddegrad og lengdegrad reverseres når breddegrad og lengdegrad leveres som en matrise. Opprinnelig ble breddegrad-lengdegradsparet brukt i både streng og i en matrise, men senere ble det reversert for å matche formatet som ble brukt av GeoJSON.
4. Ulike måter å lagre Geo Shape Data på
4.1. Punkt
POST / indeks / type {"location": {"type": "point", "coordinates": [72.57, 23.02]}}
Her er geoformtypen vi prøver å sette inn en punkt. Ta en titt på plassering felt, har vi et nestet objekt som består av felt type og koordinater. Disse metafeltene hjelper Elasticsearch med å identifisere geografisk form og dens faktiske data.
4.2. LineString
POST / indeks / type {"location": {"type": "linestring", "coordinates": [[77.57, 23.02], [77.59, 23.05]]}}
Her setter vi inn linjering geo form. Koordinatene for linjering består av to punkter, dvs. start- og sluttpunkt. LineString geo form er veldig nyttig for brukstilfeller for navigering.
4.3. Polygon
POST / indeks / type {"location": {"type": "polygon", "koordinater": [[[10.0, 0.0], [11.0, 0.0], [11.0, 1.0], [10.0, 1.0], [ 10.0, 0.0]]]}}
Her setter vi inn polygon geo form. Ta en titt på koordinater i eksemplet ovenfor, først og siste koordinater i polygon skal alltid stemme overens, dvs. en lukket polygon.
Elasticsearch støtter også andre GeoJSON-strukturer. En komplett liste over andre støttede formater er som nedenfor:
- MultiPoint
- MultiLineString
- MultiPolygon
- GeometryCollection
- Konvolutt
- Sirkel
Vi kan finne eksempler på formater som støttes ovenfor på det offisielle ES-nettstedet.
For alle strukturer, det indre type og koordinater er obligatoriske felt. Det er for øyeblikket ikke mulig å sortere og hente geografiske formfelt i Elasticsearch på grunn av deres komplekse struktur. Dermed er den eneste måten å hente ut geofelt fra kildefeltet.
5. ElasticSearch Geo Query
Nå som vi vet hvordan vi setter inn dokumenter som inneholder geoformer, la oss dykke inn i å hente disse postene ved hjelp av geoformspørsmål. Men før vi begynner å bruke Geo Queries, trenger vi følgende avhengighetsavhengigheter for å støtte Java API for Geo Queries:
org.locationtech.spatial4j spatial4j 0.7 com.vividsolutions jts 1.13 xerces xercesImpl
Vi kan også søke etter de ovennevnte avhengighetene i Maven Central repository.
Elasticsearch støtter forskjellige typer geografiske spørsmål, og de er som følger:
5.1. Geo Shape Query
Dette krever geo_shape kartlegging.
Lik geo_shape type, geo_shape bruker GeoJSON-struktur for å spørre dokumenter.
Nedenfor er et eksempelspørsmål for å hente alle dokumentene som faller innenfor gitt koordinater øverst til venstre og nederst til høyre:
{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_shape": {"region": {"shape": {"type": "envelope "," koordinater ": [[75.00, 25.0], [80.1, 30.2]]}," relation ":" innenfor "}}}}}
Her, forhold bestemmer romlige forholdsoperatører brukt på søketid.
Nedenfor er listen over støttede operatører:
- INTERSEKTER - (standard) returnerer alle dokumenter hvis geo_shape felt krysser spørringsgeometrien
- SKADE - henter alle dokumenter hvis geo_shape feltet har ingenting til felles med spørringsgeometrien
- INNENFOR - får alle dokumenter hvis geo_shape feltet er innenfor spørringsgeometrien
- INNEHOLDER - returnerer alle dokumenter hvis geo_shape feltet inneholder spørringsgeometrien
På samme måte kan vi spørre med forskjellige GeoJSON-former.
Java-kode for ovennevnte spørring er som nedenfor:
Koordinatopp Venstre = ny Koordinat (74, 31.2); Koordinere bottomRight = ny Koordinat (81.1, 24); GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery ("region", ny EnvelopeBuilder (topLeft, bottomRight) .buildGeometry ()); qb.relation (ShapeRelation.INTERSECTS);
5.2. Geo Bounding Box Query
Geo Bounding Box-spørring brukes til å hente alle dokumentene basert på punktplassering. Nedenfor er et eksempel på en avgrensningsrute:
{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_bounding_box": {"location": {"bottom_left": [28.3, 30.5], " top_right ": [31.8, 32.12]}}}}}
Java-kode for ovennevnte spørsmål er som nedenfor:
QueryBuilders .geoBoundingBoxQuery ("location"). SetCorners (31.8, 30.5, 28.3, 32.12);
Geo Bounding Box-spørring støtter lignende formater som vi har i geo_point data-type. Eksempel på spørsmål for støttede formater kan bli funnet på det offisielle nettstedet.
5.3. Geo Distance Query
Geoavstandsspørring brukes til å filtrere alle dokumenter som kommer med det angitte punktområdet.
Her er et utvalg geoavstand spørsmål:
{"query": {"bool": {"must": {"match_all": {}}, "filter": {"geo_distance": {"distance": "10miles", "location": [31.131,29.976 ]}}}}}
Og her er Java-koden for ovennevnte spørsmål:
QueryBuilders .geoDistanceQuery ("location") .point (29.976, 31.131) .distance (10, DistanceUnit.MILES);
Lik geo_point, geo avstand spørring støtter også flere formater for å sende plasseringskoordinater. Mer informasjon om støttede formater finner du på det offisielle nettstedet.
5.4. Geo Polygon Spørsmål
Et spørsmål om å filtrere alle poster som har poeng som faller innenfor den gitte polygonen av poeng.
La oss se raskt på et eksempelspørsmål:
{"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}]}}}}}
Og ved Java-koden for dette spørsmålet:
Liste allPoints = ny ArrayList (); allPoints.add (ny GeoPoint (22.733, 68.859)); allPoints.add (ny GeoPoint (24.733, 68.859)); allPoints.add (ny GeoPoint (23, 70.859)); QueryBuilders.geoPolygonQuery ("location", allPoints);
Geo Polygon Query støtter også formater nevnt nedenfor:
- lat-long som en matrise: [lon, lat]
- lat-lang som en streng: “lat, lon”
- geo hash
geo_point datatype er obligatorisk for å kunne bruke dette spørsmålet.
6. Konklusjon
I denne artikkelen diskuterte vi forskjellige kartleggingsalternativer for indeksering av geodata, dvs. geo_point og geo_shape.
Vi gikk også gjennom forskjellige måter å lagre på geodata og til slutt observerte vi geo-spørringer og Java API for å filtrere resultater ved hjelp av geo-spørringer.
Som alltid er koden tilgjengelig i dette GitHub-prosjektet.