Térinformatikai támogatás a MongoDB-ben

1. Áttekintés

Ebben az oktatóanyagban a MongoDB térinformatikai támogatását tárjuk fel.

Megbeszéljük a térinformatikai adatok tárolását, a földrajzi indexelést és a térinformatikai keresést. Több földrajzi térbeli keresési lekérdezést is használunk közel, geoWithin, és geoIntersects.

2. Térinformatikai adatok tárolása

Először nézzük meg, hogyan kell tárolni a térinformatikai adatokat a MongoDB-ben.

A MongoDB többszöröset támogat GeoJSON típusok a térinformatikai adatok tárolására. Példáink során főleg a Pont és Poligon típusok.

2.1. Pont

Ez a legalapvetőbb és leggyakoribb GeoJSON típus, és a rács egy adott pontjának képviseletére szolgál.

Itt van egy egyszerű tárgyunk helyeken Gyűjtemény, ennek terepe van elhelyezkedés mint a Pont:

{"name": "Big Ben", "location": {"koordináták": [-0.1268194, 51.5007292], "type": "Point"}}

Ne feledje, hogy először a hosszúsági érték következik, majd a szélesség.

2.2. Poligon

Poligon egy kicsit összetettebb GeoJSON típus.

Tudjuk használni Poligon hogy meghatározzon egy területet annak külső határaival és szükség esetén belső lyukakat is.

Lássunk egy másik objektumot, amelynek helyét a-nak definiáljuk Poligon:

{"név": "Hyde Park", "hely": {"koordináták": [[[-0.159381, 51.513126], [-0.189615, 51.509928], [-0.187373, 51.502442], [-0.153019, 51.503464], [ -0.159381, 51.513126]]], "type": "Polygon"}}

Ebben a példában meghatároztuk a külső határokat ábrázoló pontok tömbjét. A kötést is le kell zárnunk, hogy az utolsó pont megegyezzen az első ponttal.

Ne feledje, hogy meg kell határoznunk a külső határpontokat az óramutató járásával ellentétes irányban, a lyukakat az óramutató járásával megegyező irányban.

Ezen típusok mellett sok más típus is létezik LineString, MultiPoint, MultiPolygon, MultiLineString, és GeometryCollection.

3. Térinformatikai indexálás

Ahhoz, hogy keresési lekérdezéseket hajtsunk végre az általunk tárolt térinformatikai adatokon, létre kell hoznunk egy térinformatikai indexet elhelyezkedés terület.

Alapvetően két lehetőségünk van: 2d és 2dsphere.

De először határozzuk meg a helyünket collection:

MongoClient mongoClient = új MongoClient (); MongoDatabase db = mongoClient.getDatabase ("myMongoDb"); gyűjtemény = db.getCollection ("helyek");

3.1. 2d Térinformatikai Index

A 2d index lehetővé teszi számunkra, hogy olyan keresési lekérdezéseket hajtsunk végre, amelyek a 2d sík számításai alapján működnek.

Hozhatunk létre a 2d index a elhelyezkedés mező a Java alkalmazásban az alábbiak szerint:

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

Természetesen ugyanezt megtehetjük a mongó héj:

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

3.2. 2dsphere Térinformatikai Index

A 2dsphere Az index támogatja a gömbszámítások alapján működő lekérdezéseket.

Hasonlóképpen létrehozhatunk egy 2dsphere index a Java-ban ugyanazt használva Indexek osztály, mint fent:

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

Vagy a mongó héj:

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

4. Keresés térinformatikai lekérdezésekkel

Most az izgalmas részért keressünk földrajzi térbeli lekérdezéssel objektumokat a helyük alapján.

4.1. Query közelében

Kezdjük azzal közel. Használhatjuk a közel lekérdezés adott távolságon belüli helyek keresésére.

A közel a lekérdezés mindkettővel működik 2d és 2dsphere indexek.

A következő példában olyan helyeket keresünk, amelyek 1 km-nél kevesebb és 10 méterre vannak az adott pozíciótól:

@Test public void givenNearbyLocation_whenSearchNearby_thenFound () {Point currentLoc = new Point (new Position (-0.126821, 51.495885)); FindIterable result = collection.find (Szűrők.near ("hely", currentLoc, 1000.0, 10.0) közelében; assertNotNull (eredmény.első ()); assertEquals ("Big Ben", eredmény.első (). get ("név")); }

És a megfelelő lekérdezés a mongó héj:

db.places.find ({hely: {$ közel: {$ geometry: {type: "Point", koordináták: [-0.126821, 51.495885]}, $ maxDistance: 1000, $ minDistance: 10}}})

Ne feledje, hogy az eredmények a legközelebbi és a legtávolabbi sorrendbe vannak rendezve.

Hasonlóképpen, ha nagyon távoli helyet használunk, nem találunk közeli helyeket:

@Test public void givenFarLocation_whenSearchNearby_thenNotFound () {Point currentLoc = new Point (new Position (-0.5243333, 51.4700223)); FindIterable result = collection.find (Szűrők.közel ("hely", currentLoc, 5000.0, 10.0) közelében); assertNull (eredmény.először ()); }

Nálunk is van nearSphere módszer, amely pontosan hasonlóan működik közel, azzal a különbséggel, hogy gömbös geometria segítségével kiszámítja a távolságot.

4.2. A Query-n belül

Ezután feltárjuk a geoWithin lekérdezés.

A geoWithin A lekérdezés lehetővé teszi számunkra, hogy olyan helyeket keressünk, amelyek egy adott területen belül teljesen léteznek Geometria, mint egy kör, doboz vagy sokszög. Ez is működik mindkettővel 2d és 2dsphere indexek.

Ebben a példában olyan helyeket keresünk, amelyek az adott középponttól 5 km-es körzeten belül léteznek:

@Test public void givenNearbyLocation_whenSearchWithinCircleSphere_thenFound () {double distanceInRad = 5.0 / 6371; FindIterable eredmény = collection.find (Filters.geoWithinCenterSphere ("hely", -0.1435083, 51.4990956, distanceInRad)); assertNotNull (eredmény.első ()); assertEquals ("Big Ben", eredmény.első (). get ("név")); }

Ne feledje, hogy átalakítanunk kell a távolságot km-től radiánig (csak osszuk el a Föld sugarával).

És a kapott lekérdezés:

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

Ezután megkeressük az összes helyet, amely létezik egy téglalap „dobozban”. Meg kell határoznunk a dobozt a bal alsó és a jobb felső pozíció szerint:

@Test public void givenNearbyLocation_whenSearchWithinBox_thenFound () {double lowerLeftX = -0.1427638; dupla alsóBal = Y = 51,4991288; dupla felsőRightX = -0,1256209; dupla felsőJobbY = 51,5030272; FindIterable eredmény = collection.find (Filters.geoWithinBox ("hely", lowerLeftX, lowerLeftY, upperRightX, upperRightY)); assertNotNull (eredmény.első ()); assertEquals ("Big Ben", eredmény.első (). get ("név")); }

Itt található a megfelelő lekérdezés mongó héj:

db.places.find ({hely: {$ geoWithin: {$ mező: [[-0.1427638, 51.4991288], [-0.1256209, 51.5030272]]}}}

Végül, ha a keresni kívánt terület nem téglalap vagy kör, akkor sokszöget használhatunk egy konkrétabb terület meghatározására:

@Test public void givenNearbyLocation_whenSearchWithinPolygon_thenFound () {ArrayList pont = új ArrayList(); points.add (Arrays.asList (-0.1439, 51.4952)); points.add (Arrays.asList (-0.1121, 51.4989)); points.add (Arrays.asList (-0,13, 51,5163)); points.add (Arrays.asList (-0.1439, 51.4952)); FindIterable eredmény = collection.find (Filters.geoWithinPolygon ("hely", pontok)); assertNotNull (eredmény.első ()); assertEquals ("Big Ben", eredmény.első (). get ("név")); }

És itt van a megfelelő lekérdezés:

db.places.find ({hely: {$ geoWithin: {$ sokszög: [[-0.1439, 51.4952], [-0.1121, 51.4989], [-0.13, 51.5163], [-0.1439, 51.4952]}}})

Csak egy sokszöget határoztunk meg annak külső határaival, de lyukakat is hozzáadhatunk hozzá. Minden lyuk a Lista nak,-nek Ponts:

geoWithinPolygon ("hely", pontok, hole1, hole2, ...)

4.3. Keresztezi a lekérdezést

Végül nézzük meg a geoIntersects lekérdezés.

A geoIntersects A lekérdezés olyan objektumokat talál, amelyek legalább metszenek egy adottal Geometria. Összehasonlítva, geoWithin olyan tárgyakat talál, amelyek egy adott területen belül teljesen léteznek Geometria.

Ez a lekérdezés működik a 2dsphere csak index.

Lássuk ezt a gyakorlatban, példával bármely olyan helyre, amely metszi az a-t Poligon:

@Test public void givenNearbyLocation_whenSearchUsingIntersect_thenFound () {ArrayList pozíciók = új ArrayList (); pozíciók.add (új pozíció (-0.1439, 51.4952)); pozíciók.add (új pozíció (-0.1346, 51.4978)); pozíciók.add (új pozíció (-0,2177, 51,5135)); pozíciók.add (új pozíció (-0.1439, 51.4952)); Sokszöggeometria = új sokszög (pozíciók); FindIterable eredmény = collection.find (Filters.geoIntersects ("hely", geometria)); assertNotNull (eredmény.első ()); assertEquals ("Hyde Park", eredmény.első (). get ("név")); }

Az eredményül kapott lekérdezés:

db.places.find ({hely: {$ geoIntersects: {$ geometry: {type: "Sokszög", koordináták: [[[-0.1439, 51.4952], [-0.1346, 51.4978], [-0.2177, 51.5135], [ -0,1439, 51,4952]]]}}}})

5. Következtetés

Ebben a cikkben megtanultuk, hogyan kell tárolni a térinformatikai adatokat a MongoDB-ben, és megvizsgáltuk a különbségeket 2d és 2dsphere térinformatikai indexek. Megtanultuk azt is, hogy miként lehet keresni a MongoDB-ben földrajzi lekérdezések segítségével.

Szokás szerint a példák teljes forráskódja elérhető a GitHubon.