Geospatial Support i MongoDB

1. Oversikt

I denne veiledningen vil vi utforske Geospatial-støtten i MongoDB.

Vi diskuterer hvordan du lagrer geospatiale data, geoindeksering og geospatial søk. Vi bruker også flere geospatiale søk som nær, geoWithin, og geoIntersects.

2. Lagring av geospatiale data

La oss først se hvordan du lagrer geospatiale data i MongoDB.

MongoDB støtter flere GeoJSON typer for å lagre geodata. Gjennom eksemplene våre bruker vi hovedsakelig Punkt og Polygon typer.

2.1. Punkt

Dette er det mest grunnleggende og vanligste GeoJSON type, og den brukes til å representere ett bestemt punkt på rutenettet.

Her har vi et enkelt objekt, i vårt steder samling, som har felt plassering som en Punkt:

{"name": "Big Ben", "location": {"coordinates": [-0.1268194, 51.5007292], "type": "Point"}}

Merk at lengdegradverdien kommer først, deretter breddegraden.

2.2. Polygon

Polygon er litt mer kompleks GeoJSON type.

Vi kan bruke Polygon å definere et område med dets ytre grenser og også innvendige hull hvis nødvendig.

La oss se et annet objekt som har sin plassering definert som en Polygon:

{"name": "Hyde Park", "location": {"coordinates": [[[-0.159381, 51.513126], [-0.189615, 51.509928], [-0.187373, 51.502442], [-0.153019, 51.503464], [ -0.159381, 51.513126]]], "type": "Polygon"}}

I dette eksemplet definerte vi en rekke punkter som representerer ytre grenser. Vi må også lukke grensen slik at det siste punktet tilsvarer det første punktet.

Merk at vi må definere de ytre grensepunktene mot urviseren og hullområdene med urviseren.

I tillegg til disse typene, er det også mange andre typer som LineString, MultiPoint, MultiPolygon, MultiLineString, og GeometryCollection.

3. Geospatial indeksering

For å utføre søk på geospatiale dataene vi lagret, må vi opprette en geospatial indeks på vår plassering felt.

Vi har i utgangspunktet to alternativer: 2d og 2dsphere.

Men først, la oss definere stedene våre cvalg:

MongoClient mongoClient = ny MongoClient (); MongoDatabase db = mongoClient.getDatabase ("myMongoDb"); samling = db.getCollection ("steder");

3.1. 2d Geospatial Index

De 2d indeks gjør det mulig for oss å utføre søk som fungerer basert på beregninger av 2d-plan.

Vi kan lage en 2d indeks på plassering feltet i Java-applikasjonen vår som følger:

collection.createIndex (Indexes.geo2d ("location"));

Selvfølgelig kan vi gjøre det samme i mongo skall:

db.places.createIndex ({location: "2d"})

3.2. 2dsphere Geospatial Index

De 2dsphere indeks støtter spørsmål som fungerer basert på kuleberegninger.

På samme måte kan vi lage en 2dsphere indeks i Java ved hjelp av det samme Indekser klasse som ovenfor:

collection.createIndex (Indexes.geo2dsphere ("location"));

Eller i mongo skall:

db.places.createIndex ({location: "2dsphere"})

4. Søke ved hjelp av geospatiale spørsmål

Nå, for den spennende delen, la oss søke etter objekter basert på deres beliggenhet ved hjelp av geospatiale spørsmål.

4.1. I nærheten av spørring

La oss starte med nær. Vi kan bruke nær for å søke etter steder innenfor en gitt avstand.

De nær spørring fungerer med begge deler 2d og 2dsphere indekser.

I neste eksempel søker vi etter steder som er mindre enn 1 km og mer enn 10 meter fra den gitte posisjonen:

@Test public void givenNearbyLocation_whenSearchNearby_thenFound () {Point currentLoc = new Point (new Position (-0.126821, 51.495885)); FindIterable result = collection.find (Filters.near ("location", currentLoc, 1000.0, 10.0)); assertNotNull (result.first ()); assertEquals ("Big Ben", result.first (). get ("name")); }

Og den tilsvarende spørringen i mongo skall:

db.places.find ({location: {$ near: {$ geometry: {type: "Point", coordinates: [-0.126821, 51.495885]}, $ maxDistance: 1000, $ minDistance: 10}}})

Merk at resultatene er sortert fra nærmeste til lengst.

Tilsvarende, hvis vi bruker et veldig langt sted, finner vi ingen steder i nærheten:

@Test offentlig ugyldig givenFarLocation_whenSearchNearby_thenNotFound () {Point currentLoc = nytt punkt (ny posisjon (-0.5243333, 51.4700223)); FindIterable result = collection.find (Filters.near ("location", currentLoc, 5000.0, 10.0)); assertNull (result.first ()); }

Vi har også nær Sfæren metode, som fungerer akkurat som nær, bortsett fra at det beregner avstanden ved hjelp av sfærisk geometri.

4.2. Innen spørring

Deretter skal vi utforske geoWithin spørsmål.

De geoWithin spørring gjør det mulig for oss å søke etter steder som finnes i sin helhet Geometri, som en sirkel, boks eller polygon. Dette fungerer også med begge deler 2d og 2dsphere indekser.

I dette eksemplet leter vi etter steder som eksisterer innen en 5 km radius fra den angitte midtstillingen:

@Test public void givenNearbyLocation_whenSearchWithinCircleSphere_thenFound () {double distanceInRad = 5.0 / 6371; FindIterable result = collection.find (Filters.geoWithinCenterSphere ("location", -0.1435083, 51.4990956, distanceInRad)); assertNotNull (result.first ()); assertEquals ("Big Ben", result.first (). get ("name")); }

Merk at vi trenger å transformere avstanden fra km til radian (bare dele med jordens radius).

Og det resulterende spørsmålet:

db.places.find ({location: {$ geoWithin: {$ centerSphere: [[-0.1435083, 51.4990956], 0.0007848061528802386]}})

Deretter søker vi etter alle steder som finnes i et rektangel "boks". Vi må definere boksen etter dens nedre venstre posisjon og øvre høyre posisjon:

@Test offentlig ugyldig gittNearbyLocation_whenSearchWithinBox_thenFound () {double lowerLeftX = -0.1427638; dobbelt lavere Venstre = 51.4991288; dobbel upperRightX = -0,12256209; dobbelt upperRightY = 51.5030272; FindIterable result = collection.find (Filters.geoWithinBox ("location", lowerLeftX, lowerLeftY, upperRightX, upperRightY)); assertNotNull (result.first ()); assertEquals ("Big Ben", result.first (). get ("name")); }

Her er tilsvarende spørsmål i mongo skall:

db.places.find ({location: {$ geoWithin: {$ box: [[-0.1427638, 51.4991288], [-0.1256209, 51.5030272]]}})

Endelig, hvis området vi vil søke innenfor ikke er et rektangel eller en sirkel, kan vi bruke en polygon for å definere et mer spesifikt område:

@Test offentlig ugyldig gittNearbyLocation_whenSearchWithinPolygon_thenFound () {ArrayList poeng = ny ArrayList(); points.add (Arrays.asList (-0.1439, 51.4952)); poeng.add (Arrays.asList (-0.1121, 51.4989)); poeng.add (Arrays.asList (-0.13, 51.5163)); poeng.add (Arrays.asList (-0.1439, 51.4952)); FindIterable result = collection.find (Filters.geoWithinPolygon ("location", poeng)); assertNotNull (result.first ()); assertEquals ("Big Ben", result.first (). get ("name")); }

Og her er den tilsvarende spørringen:

db.places.find ({location: {$ geoWithin: {$ polygon: [[-0.1439, 51.4952], [-0.1121, 51.4989], [-0.13, 51.5163], [-0.1439, 51.4952]]}})

Vi definerte bare en polygon med ytre grenser, men vi kan også legge til hull i den. Hvert hull vil være a Liste av Punkts:

geoWithinPolygon ("location", poeng, hole1, hole2, ...)

4.3. Kryss spørring

Til slutt, la oss se på geoIntersects spørsmål.

De geoIntersects spørring finner gjenstander som i det minste krysser hverandre med et gitt Geometri. Ved sammenligning, geoWithin finner objekter som fullt ut eksisterer innenfor et gitt Geometri.

Dette spørsmålet fungerer med 2dsphere bare indeks.

La oss se dette i praksis, med et eksempel på å lete etter et sted som krysser en Polygon:

@Test public void givenNearbyLocation_whenSearchUsingIntersect_thenFound () {ArrayList positions = new ArrayList (); posisjoner.add (ny posisjon (-0.1439, 51.4952)); posisjoner.add (ny posisjon (-0.1346, 51.4978)); posisjoner.add (ny posisjon (-0.2177, 51.5135)); posisjoner.add (ny posisjon (-0.1439, 51.4952)); Polygon geometri = ny polygon (posisjoner); FindIterable result = collection.find (Filters.geoIntersects ("location", geometry)); assertNotNull (result.first ()); assertEquals ("Hyde Park", result.first (). get ("name")); }

Det resulterende spørsmålet:

db.places.find ({location: {$ geoIntersects: {$ geometry: {type: "Polygon", coordinates: [[[-0.1439, 51.4952], [-0.1346, 51.4978], [-0.2177, 51.5135], [ -0.1439, 51.4952]]]}}})

5. Konklusjon

I denne artikkelen lærte vi hvordan du lagrer geospatiale data i MongoDB og så på forskjellen mellom 2d og 2dsphere geospatiale indekser. Vi lærte også å søke i MongoDB ved hjelp av geospatiale spørsmål.

Som vanlig er hele kildekoden for eksemplene tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found