Geopriestorová podpora v MongoDB

1. Prehľad

V tomto tutoriáli preskúmame podporu Geospatial v MongoDB.

Budeme diskutovať o tom, ako ukladať geopriestorové údaje, geografické indexovanie a geopriestorové vyhľadávanie. Použijeme tiež niekoľko geopriestorových vyhľadávacích dotazov ako blízko, geoWithina geoIntersects.

2. Ukladanie geopriestorových údajov

Najprv sa pozrime, ako ukladať geopriestorové údaje v MongoDB.

MongoDB podporuje viac GeoJSON typy na ukladanie geopriestorových údajov. V našich príkladoch budeme hlavne používať Bod a Polygón typy.

2.1. Bod

Toto je najzákladnejšie a najbežnejšie GeoJSON typ a používa sa na predstavenie jedného konkrétneho bodu v mriežke.

Tu máme jednoduchý objekt, v našom Miesta zbierka, ktorá má pole umiestnenie ako Bod:

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

Upozorňujeme, že na prvom mieste je zemepisná dĺžka, potom zemepisná šírka.

2.2. Polygón

Polygón je o niečo zložitejšia GeoJSON typu.

Môžeme použiť Polygón definovať oblasť s jej vonkajšími hranicami a tiež vnútorné otvory, ak je to potrebné.

Pozrime sa na ďalší objekt, ktorý má svoje umiestnenie definované ako a Polygón:

{"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"}}

V tomto príklade sme definovali pole bodov, ktoré predstavujú vonkajšie hranice. Tiež musíme uzavrieť väzbu tak, aby sa posledný bod rovnal prvému bodu.

Upozorňujeme, že musíme definovať vonkajšie ohraničujúce body v smere proti smeru hodinových ručičiek a hranice otvorov v smere hodinových ručičiek.

Okrem týchto typov existuje aj veľa ďalších typov, ako je LineString, MultiPoint, MultiPolygon, MultiLineString, a GeometryCollection.

3. Geopriestorové indexovanie

Aby sme mohli vyhľadávať na geopriestorových údajoch, ktoré sme uložili, musíme na nich vytvoriť geopriestorový index umiestnenie lúka.

V zásade máme dve možnosti: 2d a 2dsphere.

Najskôr si však definujme miesta cvýber:

MongoClient mongoClient = nový MongoClient (); MongoDatabase db = mongoClient.getDatabase ("myMongoDb"); collection = db.getCollection ("places");

3.1. 2d Geopriestorový index

The 2d index nám umožňuje vykonávať vyhľadávacie dotazy, ktoré fungujú na základe výpočtov v 2D rovine.

Môžeme vytvoriť 2d index na umiestnenie v našej aplikácii Java nasledovne:

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

To isté môžeme samozrejme urobiť v mongo škrupina:

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

3.2. 2dsphere Geopriestorový index

The 2dsphere index podporuje dotazy, ktoré fungujú na základe výpočtov sféry.

Podobne môžeme vytvoriť a 2dsphere indexovať v Jave pomocou toho istého Indexy trieda ako je uvedené vyššie:

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

Alebo v mongo škrupina:

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

4. Vyhľadávanie pomocou geopriestorových dotazov

Teraz pre vzrušujúcu časť poďme hľadať objekty na základe ich polohy pomocou geopriestorových dotazov.

4.1. Blízko dotazu

Začnime s blízko. Môžeme použiť blízko dopyt na vyhľadanie miest v danej vzdialenosti.

The blízko dotaz funguje s oboma 2d a 2dsphere indexy.

V nasledujúcom príklade budeme hľadať miesta, ktoré sú od danej polohy vzdialené menej ako 1 km a viac ako 10 metrov:

@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 ("meno")); }

A zodpovedajúci dopyt v mongo škrupina:

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

Výsledky sú zoradené od najbližších po najvzdialenejšie.

Podobne, ak použijeme veľmi vzdialené miesto, nenájdeme žiadne blízke miesta:

@Test public void givenFarLocation_whenSearchNearby_thenNotFound () {Point currentLoc = new Point (new Position (-0.5243333, 51.4700223)); FindIterable result = collection.find (Filters.near ("location", currentLoc, 5000.0, 10.0)); assertNull (result.first ()); }

Máme tiež nearSphere metóda, ktorá funguje úplne rovnako blízko, až na to, že vzdialenosť počíta pomocou sférickej geometrie.

4.2. V rámci dotazu

Ďalej preskúmame geoWithin dopyt.

The geoWithin dotaz nám umožňuje vyhľadávať miesta, ktoré v danom danom mieste plne existujú Geometria, ako kruh, rámček alebo mnohouholník. Toto funguje aj s oboma 2d a 2dsphere indexy.

V tomto príklade hľadáme miesta, ktoré existujú v okruhu 5 km od danej stredovej polohy:

@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 ("meno")); }

Upozorňujeme, že musíme transformovať vzdialenosť z km na radián (stačí ho vydeliť polomerom Zeme).

A výsledný dopyt:

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

Ďalej vyhľadáme všetky miesta, ktoré existujú v obdĺžnikovom „poli“. Pole musíme definovať podľa jeho dolnej ľavej polohy a pravej hornej polohy:

@Test public void givenNearbyLocation_whenSearchWithinBox_thenFound () {double lowerLeftX = -0,1427638; double lowerLeftY = 51,4991288; dvojitá hornáRightX = -0,12566209; dvojitý vrchnýRightY = 51,5030272; FindIterable result = collection.find (Filters.geoWithinBox ("location", lowerLeftX, lowerLeftY, upperRightX, upperRightY)); assertNotNull (result.first ()); assertEquals ("Big Ben", result.first (). get ("meno")); }

Tu je zodpovedajúci dopyt mongo škrupina:

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

Nakoniec ak oblasť, v ktorej chceme hľadať, nie je obdĺžnik alebo kruh, môžeme pomocou polygónu definovať konkrétnejšiu oblasť:

@Test public void givenNearbyLocation_whenSearchWithinPolygon_thenFound () {ArrayList points = nový 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 result = collection.find (Filters.geoWithinPolygon ("umiestnenie", body)); assertNotNull (result.first ()); assertEquals ("Big Ben", result.first (). get ("meno")); }

A tu je zodpovedajúci dopyt:

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

Polygón sme definovali iba s jeho vonkajšími hranicami, môžeme mu však pridať aj otvory. Každá diera bude a Zoznam z Bods:

geoWithinPolygon ("umiestnenie", body, diera1, diera2, ...)

4.3. Prierezový dopyt

Na záver sa pozrime na geoIntersects dopyt.

The geoIntersects dopyt nájde objekty, ktoré sa minimálne pretínajú s daným Geometria. V porovnaní, geoWithin nájde objekty, ktoré plne existujú v danom rámci Geometria.

Tento dopyt funguje s 2 sféra iba index.

Pozrime sa na to v praxi, na príklade hľadania každého miesta, ktoré sa pretína s a Polygón:

@Test public void givenNearbyLocation_whenSearchUsingIntersect_thenFound () {ArrayList positions = new ArrayList (); positions.add (nová pozícia (-0,1439, 51,4952)); positions.add (nová pozícia (-0,1346, 51,4978)); positions.add (nová pozícia (-0,2177, 51,5135)); positions.add (nová pozícia (-0,1439, 51,4952)); Geometria polygónu = nový polygón (polohy); FindIterable result = collection.find (Filters.geoIntersects ("umiestnenie", geometria)); assertNotNull (result.first ()); assertEquals ("Hyde Park", result.first (). get ("meno")); }

Výsledný dopyt:

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. Záver

V tomto článku sme sa naučili, ako ukladať geopriestorové údaje v MongoDB, a pozreli sme sa na rozdiel medzi nimi 2d a 2dsphere geopriestorové indexy. Naučili sme sa tiež, ako vyhľadávať v MongoDB pomocou geopriestorových dotazov.

Celý zdrojový kód príkladov je ako obvykle k dispozícii na serveri GitHub.


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