Wie lade ich OpenStreetMap in Hive?

In einem früheren Artikel habe ich die umgekehrte Geokodierung mit Spark untersucht. Stellen Sie sich nun vor, wir stünden vor der Herausforderung der direkten Geokodierung von E-Mail-Adressen. Das heißt, Empfangen für die Adresse, die durch den Text einiger geografischer Koordinaten aufgezeichnet wurde.

Die Adressen für die Bestimmtheit sind russisch und vor allem - sie sind oft schief geschrieben, dh mit Fehlern, Unklarheiten und anderen Freuden. Diese Adressen befinden sich in der Hive-Datenbank im Hadoop-Cluster.


Nun, es scheint, wir verwenden die Google Maps-Geokodierungs-API (oder, wenn Sie die Importsubstitution unterstützen, die Yandex Maps-API) und arbeiten. Aber hier warten wir ebenso wie bei der umgekehrten Geokodierung auf einen kleinen Hinterhalt.

Oder groß, es ist wie ein Blick. Tatsache ist, dass wir diesmal ungefähr 5 Millionen Adressen verarbeiten müssen. Und vielleicht 50 - es war nicht sofort klar. Wie Sie wissen, wird Google Ihre IP-Adresse nach etwa 10.000 Adressen sperren. Yandex wird dasselbe mit Ihnen tun, obwohl dies etwas später möglich ist (z. B. 25.000 Anfragen pro Tag). Außerdem sind beide APIs REST, was bedeutet, dass es relativ langsam ist. Und selbst wenn Sie ein kostenpflichtiges Abonnement kaufen, erhöht sich die Geschwindigkeit nicht um einen Cent.

Und doch - wir haben keine Munitionsanekdote mehr.

Ich habe das Wichtigste vergessen: Unser Hadoop-Cluster befindet sich im Intranet, und Google Maps für das Unternehmen mit Yandex Maps und alle anderen sind für uns vom Cluster aus im Allgemeinen nicht zugänglich. Das heißt, wir brauchten eine autonome Lösung.

Ich werde gleich sagen - hier finden Sie keine fertige Lösung. Ich werde nur den Ansatz beschreiben, den wir anwenden möchten, und zwar etwas detaillierter - einer der Schritte auf dem langen Weg zu einer Lösung.

Natürlich hatten wir etwas in Reserve. Es gab einen internen ArcGIS-Server, den ich bereits erwähnt habe. Wir durften sie nicht steuern, aber wir durften ihre REST-Services nutzen.

Das erste, was wir gemacht haben, war es an die Aufgabe zu schrauben. Er hat uns nicht verboten, sondern manchmal nur wegen Wartungsarbeiten ausgeschaltet. Und was ist schön - es gab einen Batch-Modus der Geokodierung, wenn Sie ein Adresspaket an die Eingabe senden (nach der Konfiguration des Servers hatten wir eine Paketgröße von 1000 Stück, standardmäßig scheint etwas um eine Größenordnung oder zwei kleiner zu sein). All dies war auch nicht einfach, und wir und der ArcGIS-Support waren lange Zeit mit dem Server im Sumo-Wrestling beschäftigt, aber das ist eine andere Geschichte.

Nach all den Tricks und Wendungen konnten wir unsere fünf Millionen in ungefähr einem Tag verarbeiten. Es war notwendig, weiterzumachen und noch zu beschleunigen.

Gleichzeitig wurde klar, dass ein Geocoder mit REST höchstwahrscheinlich nicht für uns geeignet ist. Außerdem haben wir uns Nominatim, Pelias, Photon und Gisgraphie angesehen und waren im Allgemeinen mit keiner zufrieden. Qualität und Leistung (oder beides) waren alles andere als ideal.

Zum Beispiel weiß niemand, wie man Pakete geocodiert (und dies hat die Arbeit mit ArcGIS erheblich beschleunigt).

Oder Qualität - gehen Sie zum Demo-Server von gisgraphy.com und versuchen Sie, Moskau zu finden. Sie erhalten ein paar Dutzend Antworten, darunter: Moskau (eine Stadt in der Russischen Föderation), Kansas City (eine Stadt in den USA), Khimki, Kaluga, Vykhino-Zhulebino und viele andere Objekte, die ich in der Antwort des Geocoders nicht sehen möchte, wenn Suche nach Moskau.

Nun, das letzte (aber für uns nicht wichtige) Problem ist, dass die API weit entfernt von allen Geocodierern so gut durchdacht ist wie beispielsweise Google Maps. Nehmen wir an, die ArcGIS-API ist bereits viel unpraktischer und der Rest ist größtenteils noch schlimmer. Wenn Sie Adressen für die Benutzeroberfläche geocodieren, wählt in der Regel eine Person die beste Option aus. Und er macht es besser als das Programm. Und im Fall der Massengeokodierung ist, wie wir es getan haben, die Bewertung der Qualität des Ergebnisses für eine bestimmte Adresse eine der wichtigen Komponenten des Erfolgs.

Infolgedessen sind auch Optionen wie „Erweitern Sie Ihre eigenen Nominatim“ verschwunden.

Was tun?


Eine ziemlich offensichtliche Lösung war folgende: Da die Adressen nicht von irgendwoher stammen und nicht verschwinden, die Häuser nicht jeden Tag gebaut werden und die Straßen nicht gebaut werden, müssen Sie unserem Prozess lediglich eine Datenbank mit offiziell vorhandenen Adressen hinzufügen. Besser sofort mit den Koordinaten, und wenn dies nicht passiert, dann geocodieren Sie es einmal. In diesem Fall reicht es aus, wenn wir unsere Basis mit der gleichen Häufigkeit aktualisieren, mit der neue Häuser oder Straßen erscheinen, dh nicht oft.

Der erste und Hauptkandidat für die Basis bestehender Adressen ist FIAS . Warten Sie eine Minute, sagen Sie, aber FIAS hat nur wenige Millionen Adressen - und Sie haben bis zu 50 Millionen? Ja, es gibt wirklich nur ein paar Millionen Häuser . Und unsere 50 sind 50 Millionen Adressen unserer Benutzer, das heißt, dies sind die Adressen von Menschen, und sie haben plötzlich eine Wohnung in der Adresse. Fünf Millionen Häuser mit 1-100 Wohnungen, in jeder Wohnung leben mehrere Personen ... Sie verstehen alles. Und die zweite Option sind die Adressen von Büros, in denen auch ein Bürozentrum bis zu Hunderte von Räumlichkeiten hat, die manchmal vermietet werden.

Gleichzeitig benötigen wir offensichtlich keine Adresse mit der Nummer der Wohnung (oder des Büros) - erstens handelt es sich um personenbezogene Daten mit allen Konsequenzen, und zweitens sind wir immer noch nicht daran interessiert, wie sich die Wohnungen in einem bestimmten Haus befinden und wie ihre Koordinaten lauten . Es wird nur ein Haus benötigt. Für Büros ist dies nicht ganz richtig, aber der Standort von Büros in einem Gebäude nach Etagen wird immer noch nicht durch Koordinaten bestimmt.

Mit einer Basis von beispielsweise 5 Millionen (bedingt) vorhandenen Häusern können wir das Geokodierungsproblem von 50 oder 100 Millionen Adressen lösen, indem wir einfach die Wohnung oder das Büro aus der Adresse werfen und sie mit der Basis abgleichen.

Und wo bekommt man die Koordinaten der Häuser? Es gibt nur eine offensichtliche Open Source - OpenStreetMap, dort gibt es Häuser mit Geometrien und verschiedenen anderen Attributen wie der Anzahl der Stockwerke oder sogar der Farbe des Daches.

Nach all den Diskussionen hatten wir einen napoleonischen Plan. Hier ist einer:

  • Laden von Kartendaten aus OSM in Hadoop
  • Laden Sie FIAS-Daten mit Adressen hoch
  • Erstellen Sie eine Liste eindeutiger vollständiger Adressen mit Hausnummern
  • Wir haben es geocodiert, indem wir in OSM nach Adressen gesucht haben. Was wir nicht gefunden haben, ist über ArcGIS


Wir bekommen die Basis von Häusern mit Längen- und Breitengrad. Viel Spaß. Nutzen Sie die Vorteile. Trinkgeld (Witz).

In diesem Artikel werde ich Ihnen erzählen, wie wir den ersten Punkt dieses Plans umgesetzt haben.

Was ist OpenStreetMap?


Wenn Sie OSM aus Datensicht betrachten, können Sie sich die Karten in Form von drei Tabellen vorstellen:

  • Punkte
  • Linien (Wege)
  • Beziehungen


Reale Schemata dieser Daten werden unten angegeben.

Nur Punkte haben Koordinaten (Breite und Länge in Grad). Linien sind eine geordnete Folge von Punkten. Beziehungen sind eine Reihe von Punkten und Linien, von denen jeder eine Rolle spielt .

Alles andere sind die sogenannten Tags. Das ist zum Beispiel ein Geldautomat oder ein Geschäft oder ein Eingang zur U-Bahn - es kann ein Punkt sein, der mit dem Tag amenity = atm oder shop = etwas oder etwas anderes ausgestattet ist. Es gibt ein Verzeichnis offiziell empfohlener Tags (für jede anwendbare Sprache und jedes Land können sie teilweise ihre eigenen sein) und die Praxis, nicht standardmäßige Tags zu erfinden.

Zusätzlich zu den Tags verfügt jedes Element der Karte über eine eindeutige numerische ID sowie einige Attribute, die sich auf den Verlauf beziehen - wer wann bearbeitet hat, Nummer bearbeitet usw.

Die Datenbank mit der Karte ist in verschiedenen Formaten erhältlich:
- pbf ist Google Protobuf, ein tragbares Datenserialisierungsformat.
- XML ​​ist offensichtlich XML. Viel mehr Volumen.

Sie müssen verstehen, dass die Datenbank täglich aktualisiert wird. Daher sind die Entladungen vollständig und inkrementell.

Wir haben PBF als kompakter gewählt.

Um es in Hadoop zu lesen, gibt es eine speziell für OSM entwickelte Java-API namens Osmoseprojekt. Im Prinzip ist die Arbeit damit einfach: Sie laden eine Datei hoch und durchlaufen die Kartenelemente. Fügen Sie die Punkte an einer Stelle hinzu, die Linien an einer anderen, die Beziehung an der dritten. Grundsätzlich reichen Osmose und beispielsweise Spark bereits aus, um alle Daten herunterzuladen.

Glücklicherweise kam mir bei der Implementierung meines Fahrrads der Gedanke, im Internet nach der Konvertierung von OSM in die in Hadoop - Parkett (Parkett) und Avro akzeptierten Formate zu suchen. In gewisser Weise sind beide Analoga von PBF, so dass die Möglichkeit bestand, einen Konverter zu finden. Und er wurde gefunden, aber keiner.

Lernen Sie OSM Parquetizer kennen


Sehen Sie, was ich gefunden habe!

Für faule Leute - direkt in der Readme-Datei des Projekts in der ersten Zeile steht: Telenav veröffentlicht wöchentliche Downloads des Planeten an die Adresse .

Für sehr faule Leute: Machen Sie sich bereit, ungefähr 700 Gigabyte zu versenden;) Nun, wenn Sie auf jeden Fall einen Planeten brauchen. Normalerweise kommt man beispielsweise mit Europa aus.

Wenn Sie nicht laden möchten, sieht der Vorgang folgendermaßen aus: Laden Sie eine Karte im PBF-Format herunter, z. B. von einer Geofabrik . Dies sind 2,5 Gigabyte, wenn Sie Russland brauchen, und 19, wenn Europa. Auch nicht wenig, aber Sie können fein gehackte Proben finden. Legen Sie als Nächstes die Datei auf die Festplatte und führen Sie das Programm aus:

java -jar ./osm-parquetizer.jar russia-latest.osm.pbf 

Nach einigen Minuten oder sogar Sekunden erhalten Sie je nach Leistung Ihres Geräts drei Dateien im Parkettformat. So sieht der Autor aus (er kommt aus Rumänien):

 -rw-r--r-- 1 adrianbona adrianbona 145M Apr 3 19:57 romania-latest.osm.pbf -rw-r--r-- 1 adrianbona adrianbona 372M Apr 3 19:58 romania-latest.osm.pbf.node.parquet -rw-r--r-- 1 adrianbona adrianbona 1.1M Apr 3 19:58 romania-latest.osm.pbf.relation.parquet -rw-r--r-- 1 adrianbona adrianbona 123M Apr 3 19:58 romania-latest.osm.pbf.way.parquet 

Schemata der empfangenen Parkettdateien:

node
|-- id: long
|-- version: integer
|-- timestamp: long
|-- changeset: long
|-- uid: integer
|-- user_sid: string
|-- tags: array
| |-- element: struct
| | |-- key: string
| | |-- value: string
|-- latitude: double
|-- longitude: double

way
|-- id: long
|-- version: integer
|-- timestamp: long
|-- changeset: long
|-- uid: integer
|-- user_sid: string
|-- tags: array
| |-- element: struct
| | |-- key: string
| | |-- value: string
|-- nodes: array
| |-- element: struct
| | |-- index: integer
| | |-- nodeId: long

relation
|-- id: long
|-- version: integer
|-- timestamp: long
|-- changeset: long
|-- uid: integer
|-- user_sid: string
|-- tags: array
| |-- element: struct
| | |-- key: string
| | |-- value: string
|-- members: array
| |-- element: struct
| | |-- id: long
| | |-- role: string
| | |-- type: string


Wie Sie sehen, ist hier alles einfach. Dann machen wir folgendes:

  • Wir legen Dateien mit dem Befehl hdfs dfs -put auf dem Hadoop-Cluster ab
  • Lassen Sie uns in Hue ein Schema / eine Basis und drei Tabellen dafür erstellen, basierend auf den obigen Daten
  • Führen Sie select * aus osm.nodes aus und genießen Sie das Ergebnis.

Eine kleine Nuance: In unserer Version von Hive (und möglicherweise auch in Ihrer) können keine Tabellen basierend auf dem Schema von Parquet erstellt werden. Sie müssen entweder das Obige in CREATE TABLE konvertieren (was im Allgemeinen nicht schwierig ist und ich dies als Heimübung für die Leser belasse) oder etwas kniffliger vorgehen: Spark kann das Diagramm und die Daten vom Boden aus lesen und darauf basierend temporäre Tabellen erstellen . So können wir die Daten in Spark Shell folgendermaßen lesen:

 val nodeDF = sqlContext.read.parquet("file:/tmp/osm/romania-latest.osm.pbf.node.parquet") nodeDF.createOrReplaceTempView("nodes") 

Dann können Sie bereits Tabellen in Hive mit LIKE-Knoten erstellen.

Eine weitere Bemerkung für faule Leute: Der Autor hat ein so wunderbares Beispiel , aus dem im Allgemeinen alles klar wird (na ja, wenn Sie Spark besitzen). Dies ist natürlich nicht Spark Shell, sondern das Databricks Notebook, aber ich habe ungefähr 15 Minuten gebraucht, um auf eine Tastatur zu tippen, um sie in eine andere zu übersetzen. Und in 30-40 Minuten war es möglich, alles mit einigen Analoga, die sich geringfügig von Spark unterscheiden, in Abfragen für Hive umzuwandeln.

Beispiel für eine echte Anfrage


Was können wir aus dieser Datenbank in ihrer aktuellen Form erhalten? Im Allgemeinen ziemlich viel. Wenn Sie über einen Hive oder Spark, ein Spatial Framework, eine Geometry API oder eine der Alternativen GeoSpark oder beispielsweise GeoMesa verfügen, können Sie auf dieser Basis viele verschiedene Probleme lösen.

Sehen wir uns ein Beispiel an. Der einfachste Weg, um mit Punkten zu arbeiten. Eine Abfrage zum Abrufen einer Liste von Geldautomaten mit ihren Koordinaten sieht beispielsweise folgendermaßen aus:

 select * from nodes where tags['amenity']='atm' 

Wie man eine solche Abfrage erstellt, kann man erraten, indem man die Seite im Wiki liest. Dort finden Sie, was andere Tags sind, und einige davon können in Ihrer Anfrage anstelle von * enthalten sein, beispielsweise in Form von Tags ['operator'], um den Namen der Bank anzuzeigen.

Aus derselben Seite folgt, dass ATM-Markups in Form von Tags möglich sind. Amenity = bank und atm = yes. Leider gibt es solche Unklarheiten überall in OSM.

Wenn Sie ein Anfänger sind und sich nur mit OSM vertraut machen, empfehle ich dringend, den Overpass-Turbo (anhand guter Beispiele im Wiki) zu beherrschen. Dies ist ein Tool, mit dem Sie verschiedene Arten von Suchvorgängen für Kartendaten durchführen können, sowohl mit geometrischen Bedingungen als auch mit Bedingungen für Tags.

Und wo sind die Adressen?


Gute Frage. Adressen in OSM sind Kartenelemente, die mit addr: * -Tags versehen sind, d.h. beginnend mit addr. Beschreibung finden Sie hier . Wenn Sie alles wissen, was ich oben angegeben habe, können Sie im Prinzip bereits eine Arbeitsanfrage schreiben:

 select * from nodes where tags['addr:housenumber']!=null 

Welche Probleme erwarten uns hier? Erstens werden Adressen sowohl auf Punkten (z. B. Gebäudeeingängen) als auch auf Polygonen platziert, d. H. auf Wegen. Also müssen wir die Anfrage zumindest duplizieren. Und zweitens ist das Wiki auf der oben genannten Seite im Klartext geschrieben. Es wird nicht empfohlen, Tags zu setzen, die Stadt, Region, Region und Land angeben. Dies muss jedoch geometrisch berechnet werden. Wie kann man das machen? Im Allgemeinen ist dies praktisch die Aufgabe der umgekehrten Geokodierung mit Lichtmodifikationen, und sie wurde in einem früheren Beitrag beschrieben.

Das heißt, Sie müssen im Allgemeinen administrative Grenzen finden und für alle darin enthaltenen Adressen die Adresse zum Bereich und zu allen oben genannten hinzufügen. Hier wird beschrieben, wie die Grenzen von Verwaltungseinheiten angeordnet sind.

Im Allgemeinen ist diese Aufgabe nicht allzu einfach, aber sie kann gelöst werden, und sie wird nicht durch Geokodierung gelöst, sondern durch Herunterladen von OSM-Updates in unsere Datenbank in einer entspannten Atmosphäre.

Was ist nützlich als nächstes zu tun


Im Prinzip können Sie bereits mit den vorhandenen Knoten-, Weg- und Beziehungstabellen arbeiten. Es ist jedoch besser, das Schema ein wenig zu ändern, damit es besser für Hive und Spark geeignet ist. Tatsache ist, dass das OSM-Schema vollständig normalisiert ist und Wege und Beziehungen überhaupt keine Koordinaten enthalten. Um ein Polygon für den Weg zu erstellen, müssen Sie sich mit Knoten verbinden. Ich würde empfehlen, diese Operation sofort auszuführen und die Polygone entweder als Array von Strukturen (Hive kann mit den zusammengesetzten Typen Array, Map und Struct arbeiten) oder sofort als serialisierte Darstellung beispielsweise der Geometry-Klasse zu speichern. Wie das geht, zeigt das Beispiel des Autor Parkettierers.

Sie können eine ähnliche Operation auf der Ebene der Beziehungen wiederholen, wenn Sie möchten, aber es lohnt sich kaum. Erstens benötigen Sie nicht immer alle Elemente einer Beziehung, und zweitens sind die Beziehungen selbst in OSM viel kleiner.

Konverter zu Avro


Hier ist ein weiterer Konverter, diesmal in das Avro-Format. Und hier wird beschrieben, wo man die fertigen Dateien bekommt. Ich habe die Größen nicht gemessen, aber ich denke, dass ungefähr 15-20 Dateien pro Planet mit PBF vergleichbar sein sollten. Das heißt, das sind Gigabyte und vieles mehr.

Einige Schlussfolgerungen


Und wo ist Geokodierung, fragst du? Ja, das Herunterladen von Karten und das Extrahieren von Adressen ist nur ein Teil der Gesamtaufgabe. Ich hoffe es kommt dazu.

Source: https://habr.com/ru/post/de438374/


All Articles