Einführung in die Nutzung von Geodaten in der NoSQL-Datenbank MongoDB

MongoDB trifft Geo Data
Kommentare

Tools
Als sinnvoll werden Sie sicherlich nach kurzer Zeit auch die Nutzung eines GUI-Tools für die Arbeit mit MongoDB-Datenbanken erachten. Hier gibt es einige subjektive Tendenzen, aber schauen Sie sich

Tools

Als sinnvoll werden Sie sicherlich nach kurzer Zeit auch die Nutzung eines GUI-Tools für die Arbeit mit MongoDB-Datenbanken erachten. Hier gibt es einige subjektive Tendenzen, aber schauen Sie sich vielleicht die nachfolgenden Empfehlungen an: [2] nutzt Silverlight und ist damit auf vielen Maschinen nutzbar. Für den Mac empfiehlt sich MongoHub, interessant ist hier auch der Import und Export von MySQL-Daten. Mit MongoHub können auch MapReduce-Anfragen formuliert werden. Daneben gibt es eine Vielzahl von Webvarianten [3] und Java-basierten Tools.

Umkreissuche eher pragmatisch

Vermutlich ist das nicht der erste Artikel, in dem Sie etwas über Geo-Location-Programmierung lesen, vielleicht aber der erste, der Sie nicht mit den üblichen „Problemen“ konfrontiert.

Alle Koordinaten auf der Erde befinden sich natürlich auf einer Kugel, und damit führt die Entfernung zwischen zwei Punkten immer über die Oberfläche und nicht direkt durch jene blaue Kugel. Betrachten wir jedoch ein echtes Problem, wie die Umkreissuche, dann ergeben sich zwei neue Betrachtungsweisen. Zum einen werden wir es im Gewirr unserer Städte kaum schaffen, den Weg zwischen zwei Punkten auf dem direkten Weg zurückzulegen. Entwickeln wir nicht gerade eine Anwendung für eine Helikopterstaffel, dann ist der reale Weg sicherlich größer als der theoretisch errechenbare direkte. Zum anderen bewegen wir uns in der Regel in Dimensionen von „Umkreisen“ von vielleicht zehn bis 50 Kilometern. Der Unterschied zwischen einer mathematisch (die Kugeloberfläche berücksichtigende) und einer vereinfachten Sichtweise, die von einer flachen Erde ausgeht, ist hier kaum merklich. Auch die mathematisch korrekte Herleitung erzeugt zumeist Vereinfachungen. Die Erde ist eben keine exakte Kugel, sondern hat einige Berge und Täler. Hinzu kommt eine Abplattung an den Polen. Oft wird daneben der Radius der Erde idealisiert. In Kombination mit der nicht direkten Erreichbarkeit gibt man sich vielleicht pragmatisch und verzichtet bewusst auf die mathematisch exakte Darstellung.

Insbesondere bei großen Datenmengen bringt nur eine Strategie den Erfolg, die entweder ganz auf die mathematisch exakte Betrachtung verzichtet oder sie erst später anwendet. Nach einer ersten „groben“ Suche mit einem vereinfachten Verfahren werden die Ergebnisse zunächst eingeschränkt und danach wird in den Randbereichen die exakte Untersuchung anwendet. In den folgenden Beispielen verzichten wir bewusst auf diese Form der Nachuntersuchung. Wir nutzen lediglich die bereits in MongoDB vorhandene, vereinfachte Form der Umkreissuche. Seien Sie sich dessen bewusst und betrachten Sie Ihr Problem in Bezug auf die Notwendigkeit der exakteren Umkreissuche. Als eine Quelle zur Lösung sei hier auf [4] verwiesen.

Los geht’s in PHP

Sehen wir uns die Nutzung von MongoDB aus PHP heraus an. Zunächst wollen wir uns ein wenig Datenmaterial beschaffen, mit dem wir arbeiten können. Hier nutzen wir eine Liste der US-Postleitzahlenbereiche mit ihren Geo-Koordinaten und Städtenamen. Den Aufbau (im JSON-Format) sehen Sie in Listing 1. Bitte beachten Sie, dass sich die Geo-Position einfach als „Objekt“ (mit den Attributen x und y) mit dem loc in allen Sätzen befindet. Insgesamt haben wir hier etwa 76 000 Postleitzahlbereiche. Die Werte für die Längengrade sind leider mit dem falschen Vorzeichen angegeben, im Rahmen der folgenden Beispiele nutzen wir aber auch entsprechend „falsche“ Ursprungswerte, womit sich mögliche Probleme umgehen lassen.

Listing 1: Ein Datensatz aus zips.json

{"city": "ACMAR", "zip": "35004", "loc": {"y": 33.584131999999997, "x": 86.515569999999997}, "pop": 6055, "state": "AL"}
{"city": "ADAMSVILLE", "zip": "35005", "loc": {"y": 33.588436999999999, "x": 86.959727000000001}, "pop": 10616, "s54546tate": "AL"}
{"city": "ADGER", "zip": "35006", "loc": {"y": 33.434277000000002, "x": 87.167455000000004}, "pop": 3205, "state": "AL"}

Folgend finden Sie einen Weg, der zeigt, wie die Daten in eine MongoDB-Installation zu importieren sind. Das Tool befindet sich in ihrem mongodb-bin-Verzeichnis. Hiermit importieren wir die Daten in die Datenbank us_city in die Collection zips auf dem Server mongodb20:

./mongoimport -h mongodb20 -d us_city -c zips zips.json

Nun beginnen wir mit einer einfachen Abfrage in Listing 2. Der PHP-Treiber arbeitet im Wesentlichen objektorientiert, die Objekte nehmen aber oft komplexe Parameter in Form von assoziativen Arrays entgegen. Das Basisobjekt Mongo stellt die Verbindung zur Datenbank her und ermöglicht dann die Auswahl einer Datenbank. Das Wrapper-Objekt MongoCollection dient zur Formulierung der Abfrage und gibt nach der Ausführung einen so genannten Cursor zurück. In PHP ist das ein Iterator, der den Zugriff auf die Ergebnisdokumente ermöglicht. In unserem Beispiel haben wir eine sehr einfache Abfrage genutzt, die die Ergebnisse auf Einträge im Staat New York beschränkt. Hier sind aber durchaus auch komplexere Möglichkeiten gegeben, dabei bleibt das Prinzip gleich: ein Array aufbauen, dessen Keys die „Felder“ angeben. Die Values sind entweder exakte Matches oder wiederum Arrays, die die Abfrage bestimmen.

Listing 2: Einfacher Query auf den Daten

$m = new Mongo("mongodb://mongodb20:27017");
$db = $m->selectDB('us_city');
$zips = new MongoCollection($db, 'zips');

$query['state'] = 'NY';

$cur = $zips->find($query);
foreach ($cur as $doc) {
    echo '
' . print_r($doc, true) . '

';
}

Geo-Abfragen

Zur Formulierung einer location-basierten Abfrage können wir in MongoDB einfach eine Abfrage mithilfe des $near-Operators formulieren. Dabei beziehen wir uns zunächst auf das Feld im Objekt (loc), das eine zweidimensionale Koordinate speichert. Hier müssen die Daten in der Reihenfolge Lng/Lat vorliegen, die Namen der Felder (bei uns x/y) sind unwesentlich.

Die echte Abfrage formulieren Sie nun mit den beiden Operatoren $near und $maxDistance, wobei $near die Ursprungskoordinate (im Format der Dokumentdaten) und $maxDistance den Umkreis angibt. Passen Sie hier auf die Nutzung von einfachen Anführungszeichen auf, damit keine Variablensubstitution eingesetzt wird. Hier muss auch beachtet werden, dass die Distanz in der Einheit der Dokumentdaten anzugeben ist. Faktisch entsprechen damit 0,01 etwa 1,1 Kilometern. MongoDB nutzt hier lediglich eine vereinfachte Abstandsrechnung ohne Kugelgeometrie. Das Beispiel befindet sich in Listing 3. Folgend sehen Sie die Anlage eines so genannten geo-spatial index. Die Angabe des Feldnamens und der Marker 2D erzeugt den entsprechend Index, der im Wesentlichen die Abfragegeschwindigkeit steigert:

Listing 3: Abruf von Daten mit $near

$zipsNearBy = new MongoCollection($db, 'zips');

$nearQuery['loc'] = array(
    '$near' => array(
      floatval('40.708451'),
      floatval('74.013474')),
     '$maxDistance' => floatval('0.01'));

$cur = $zipsNearBy->find($nearQuery)->limit(10);
foreach ($cur as $doc) {
    echo '
' . print_r($doc, true) . '

';
}

$m = new Mongo("mongodb://mongodb20:27017");
$db = $m->selectDB('us_city');
$zips->ensureIndex(array('loc' => '2d'));

Daneben bietet MongoDB auch die Nutzung des so genannten geoNear Commands. Die Nutzung und das Ergebnis befinden sich in Listing 4. Die Rückgabe des Commands enthält dann die Ergebnisdaten für jeden gefundenen Satz, aber auch den Abstand zum Ursprung (da spherical => true). Hier arbeitet MongoDB mit einem Verfahren, bei dem zunächst die Näherung und Einschränkung mit dem einfachen Verfahren und dann das exakte Verfahren angewendet wird.

Listing 4: Nutzung des geoNear Commands

$nearData = $db->command(
      array('geoNear' => 'zips',
        'near' => array(floatval('40.708451'), floatval('74.013474')),
        'spherical' => true,
        'num' => 10) );
Fazit

Der Vorteil zur Nutzung von MongoDB für geobasierte Entwicklung liegt in der kurzen Einarbeitung. Der Einsatz auch bei sehr großen Datenmengen ist praxiserprobt. Neben der reinen Umkreissuche bietet MongoDB aber auch noch weitere Geo-Funktionen und entwickelt sich hier rasant weiter.

Carsten Harnisch ist Technology Scout und arbeitet als Geschäftsführer bei der InTradeSys Limited.
MapReduce

Der Begriff „MapReduce“ kommt ursprünglich aus der von Google genutzten Methode zur Ermittlung von Suchergebnissen. Basis des zugrunde liegenden Problems ist es, riesige Datenmenge durchsuchbar zu machen. Da die Datenmenge hier die Kapazität einer einzelnen Menge deutlich übersteigt, wurde ein Verfahren gesucht, das sowohl die Daten als auch die Verarbeitung auf mehrere Maschinen verteilen kann.

Das Grundprinzip ist die Anwendung von zwei Methoden: Zunächst wird die Map-Methode für jedes einzelne Dokument aufgerufen. Die Methode gibt hier immer ein Key-Value-Paar zurück; die Ausgaben der einzelnen Map-Methoden-Aufrufe sammeln sich als Arrays unter den einzelnen Keys. Eventuell müssen nun noch die Ergebnisse von mehreren Maschinen gesammelt und weiter kombiniert werden. Die finalen Value Arrays werden dann je Key an die Reduce-Methode übergeben. Hier wird nun der kombinierte Wert zurückgeliefert. Das finale Ergebnis hat dann wieder die gleiche Form wie die Ausgabe der Map-Methode.

Beispielsweise soll die Anzahl der Vorkommnisse der unterschiedlichen Buchstaben in allen Dokumenten ermittelt werden. Die Map-Methode kann nun je Buchstabe (als Key) die Anzahl der Vorkommnisse als Value zurückliefern. Nach der Sammlung aller Ergebnisse wird je Buchstabe (als Key) die kombinierte Liste der Anzahlen (als Value Array) an die Reduce-Methode übergeben. Diese addiert einfach die Anzahlen zu einem finalen Wert (für den Buchstaben) zusammen. Das Ergebnis ist eine Liste von Key-Value-Paaren mit dem entsprechenden Buchstaben und der Gesamtanzahl.

In MongoDB wird das Ergebnis des MapReduce-Jobs als Collection abgelegt und kann danach abgerufen werden. Im Gegensatz zu anderen NoSQL-Vertretern müssen neue oder veränderte Dokumente selbst (durch den Entwickler) in die Ergebnis-Collection eingearbeitet werden (inkrementelles Merging).

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -