Dec 6th: [ES] Cargando datos de OSM en Elasticsearch

Versión en inglés

Una de las tareas más comunes para los usuarios del stack de Elastic que trabajan con datos geoespaciales tiene que ver con la carga de datos en Elasticsearch. En la documentación de Kibana 7.10 puedes encontrar detalles sobre cómo cargar datos. Hace un tiempo escribimos un artículo en nuestro blog que introducía ogr2ogr, una herramienta de la biblioteca GDAL que facilita la carga en Elasticsearch desde docenas de formatos geoespaciales.

En este artículo del calendario de Adviento desarrollamos un ejemplo de este flujo de trabajo usando Docker para aprovechar la última versión de GDAL y OpenStreetMap, una alternativa muy popular de datos abiertos sobre Puntos de Interés (POI).

Con Docker, evitamos problemas con versiones y entornos locales, y podemos utilizar las últimas versiones de GDAL, independientemente del Sistema Operativo de nuestro equipo. Puedes también desde luego instalar GDAL, pero debes asegurarte de disponer de al menos la versión 3.1.

Configuración: crear un despliegue de Elastic

Puedes dirigirte a https://cloud.elastic.co y crear un nuevo despliegue. Para esta prueba hemos creado un cluster en la versión 7.9.3 con un nodo de Elasticsearch de 4GB de RAM y un nodo de Kibana de 2GB de RAM. Coloca los detalles de acceso al cluster en un fichero .env como este:

ELASTIC_HOST=<host-de-tu-cluster>
ELASTIC_PORT=9243
ELASTIC_USER=<usuario>
ELASTIC_PASSWORD=<password>

ELASTIC_URL="https://${ELASTIC_USER}:${ELASTIC_PASSWORD}@${ELASTIC_HOST}:${ELASTIC_PORT}"

Carga las variables y comprueba que todo está correcto ejecutando la herramienta ogrinfo de este modo:

$ source .env
$ docker run --rm \
 osgeo/gdal:alpine-small-latest \
 ogrinfo -summary "ES:${ELASTIC_URL}"

INFO: Open of `ES:https://<your-user> :<your-host>:<your-port>'
      using driver `Elasticsearch' successful.
1: .kibana-event-log-7.9.3-000001 (None)
2: .apm-custom-link (None)
3: .kibana_task_manager_1 (None)
4: .apm-agent-configuration (None)
5: .kibana_1 (None)

Todo correcto, hemos podido conectar y comprobar que nuestro cluster no dispone de ningún índice con campos geoespaciales.

Importar Puntos de Interés desde OpenStreetMap

Obtener los datos

Vamos a usar para empezar los datos de Andorra para un paso inicial, y después trabajaremos con el estado de Nueva York como nuestro juego de datos principal. Ambos datasets pueden descargarse en formato pbf desde https://download.geofabrik.de.

$ wget https://download.geofabrik.de/europe/andorra-latest.osm.pbf
$ wget https://download.geofabrik.de/north-america/us/new-york-latest.osm.pbf

Personalizar la configuración de OSM

El driver de OGR para OSM es demasiado genérico para nosotros ya que queremos enfocarnos en las propiedades relacionadas con los puntos de interés. Por eso vamos a crear un fichero osmconf.ini en el que vamos a especificar las etiquetas que que queremos cargar de los puntos de OSM.

[points]
osm_id=yes
osm_version=yes
osm_timestamp=yes
osm_uid=no
osm_user=no
osm_changeset=no

attributes=name,amenity,shop,leisure,office,wheelchair,phone,website,twitter,facebook

unsignificant=created_by,converted_by,source,time,ele,attribution
ignore=created_by,converted_by,source,time,ele,note,todo,openGeoDB:,fixme,FIXME

Crear el mapping

El siguiente paso es crear el fichero de mapping para personalizar los campos de nuestro índice. Para este paso vamos a usar el fichero andorra-latest.osm.pbf ya que es pequeño y se ejecutará más rápidamente. Veamos el comando que vamos a ejecutar y explicaremos los diferentes parámetros y opciones:

$ docker run \
  --rm -u $(id -u ${USER}):$(id -g ${USER}) `#1`\
  -v "${PWD}:/tmp/ogr" `#2`\
  -e OSM_CONFIG_FILE="/tmp/ogr/osmconf.ini"  `#3`\
 osgeo/gdal:alpine-small-latest \
 ogr2ogr -progress \
  -nln osm -overwrite `#4`\
  -sql "select * from points where amenity is not null or shop is not null or leisure is not null or office is not null" `#5`\
  -lco WRITE_MAPPING="/tmp/ogr/osm_mapping.json" `#6`\
  -lco GEOM_MAPPING_TYPE="GEO_SHAPE" `#7`\
  -lco GEOMETRY_NAME=location `#8`\
  ES:${ELASTIC_URL} `#9`\
  /tmp/ogr/andorra-latest.osm.pbf #10
  1. Ejecutaremos un contenedor efímero de Docker, con nuestro usuario y grupo.
  2. Montaremos nuestra carpeta actuar dentro del contenedor en /tmp/ogr.
  3. Pasaremos la variable de entorno para configurar el fichero de OSM.
  4. Definiremos el nombre de nuestra capa y que deseamos recrearla si ya existe.
  5. Filtraremos solo los datos que nos interesan, puedes configurar esta consulta para tus propósitos y filtrar por otros atributos o condiciones.
  6. Escribiremos el fichero de mapping en la carpeta que hemos montado.
  7. Utilizaremos el tipo de campo geo_shape
  8. Especificamos el nombre del campo geométrico
  9. URL del cluster de destino.
  10. Ubicación de nuestro dataset de origen.

Este comando generará un índice osm vacío en nuestro cluster (pero no hay que preocuparse de esto ahora) y más importante, un fichero de mapping llamado osm_mapping.json. El siguiente paso será abrir este fichero y adaptarlo a nuestras necesidades. En este ejemplo vamos a convertir los campos de algunas etiquetas de OSM en tipo keyword para poder agregarlos, y vamos a corregir la definición del formato de fecha para el campo osm_timestamp.

{
    "properties": {
        "osm_id": { "type": "text" },
        "osm_version": { "type": "integer" },
        "osm_timestamp": {
            "type": "date",
            "format": "yyyy\/MM\/dd HH:mm:ss.SSS"
        },
        "name": { "type": "text" },
        "amenity": { "type": "keyword" },
        "shop": { "type": "keyword" },
        "leisure": { "type": "keyword" },
        "office": { "type": "keyword" },
        "wheelchair": { "type": "keyword" },
        "phone": { "type": "text" },
        "website": { "type": "text" },
        "twitter": { "type": "text" },
        "facebook": { "type": "text" },
        "other_tags": { "type": "text" },
        "location": { "type": "geo_shape" }
    },
    "_meta": {
        "fid": "ogc_fid",
        "geomfields": { "location": "POINT" }
    }
}

Escribir los datos

Ahora ya estamos listos para cargar nuestro dataset de Nueva York. El comando es muy similar al anterior, simplemente hay que cambiar el parámetro de creación de capa WRITE_MAPPING por el parámetro MAPPING.

$ docker run \
  --rm -u $(id -u ${USER}):$(id -g ${USER})\
  -v "${PWD}:/tmp/ogr" \
  -e OSM_CONFIG_FILE="/tmp/ogr/osmconf.ini"\
 osgeo/gdal:alpine-small-latest \
 ogr2ogr -progress \
  -nln osm -overwrite \
  -sql "select * from points where amenity is not null or shop is not null or leisure is not null or office is not null" \
  -lco MAPPING="/tmp/ogr/osm_mapping.json" \
  -lco GEOM_MAPPING_TYPE="GEO_SHAPE" \
  -lco GEOMETRY_NAME=location \
  ES:${ELASTIC_URL} \
  /tmp/ogr/new-york-latest.osm.pbf

Tras unos instantes tu índice se creará. A continuación puedes comprobar los detalles del índice ejecutando otra vez el comando ogrinfo:

$ docker run --rm \
 osgeo/gdal:alpine-small-latest \
 ogrinfo -noextent -summary "ES:${ELASTIC_URL}" osm 

INFO: Open of `ES:https://<your-user> :<your-host>:<your-port>'
      using driver `Elasticsearch' successful.

Layer name: osm
Geometry: Point
Feature Count: 84350
Layer SRS WKT:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
FID Column = ogc_fid
Geometry Column = location
_id: String (0.0)
amenity: String (0.0)
facebook: String (0.0)
leisure: String (0.0)
name: String (0.0)
office: String (0.0)
osm_id: String (0.0)
osm_timestamp: DateTime (0.0)
osm_version: Integer (0.0)
other_tags: String (0.0)
phone: String (0.0)
shop: String (0.0)
twitter: String (0.0)
website: String (0.0)
wheelchair: String (0.0)

Nota: asegúrate de utilizar el parámetro -noextent o el comando provocará una descarga completa del juego de datos.

Visualizar en Kibana

Con nuestros datos cargados en el índice, estamos listos para visualizarlos en Elastic Maps, pero primero como siempre, tenemos que crear un index pattern utilizando el campo osm_timestamp como fecha del patrón.

Ahora podemos ir a la aplicación Discover y explorar cómo los registros se han ido agregando a la base de datos de OSM a lo largo de los últimos años.

Si haces clic en el campo location puedes crear automáticamente un mapa con este índice como capa de trabajo.

Desde aquí ya está todo listo para visualizar tus puntos de interés según sus diferente propiedades, hacer búsquedas, agregarlos en cuadrículas y mapas de calor, verlos junto con tus datos de negocio, etc. Puedes aprender más sobre las capacidades de Elastic Maps en la documentación

Happy mapping!!

2 Likes

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.