Index Polygons and MultiPolygons with logstash

Hi

I use ES to index geo-shapes like Polygon and MultiPolygon from CSV via logstash but I can't find a way to make ES ingest properly the datas... I use the following code but it failed for Polygon with holes and MultiPolygons... So it's not very good at all :wink:

input {
    stdin {}
}
filter {
	csv {
		columns => [
			"CODE_IRIS","NOM_IRIS","NOM_COM","INSEE_COM","type","coordinates"
		]
		separator => ","
		skip_empty_columns => true
		}
	if [TYPECOM] == "CODE_IRIS" {
        drop { }
    }
	mutate {
        convert => { "coordinates" => "string" }
    }

	if [type] == "MultiPolygon" {
		ruby {
			code => '
				polygons = event.get("coordinates").split("), (").map { |polygon| polygon.tr("()", "") }

				multi_polygon_coordinates = []
				polygons.each do |polygon|
					polygon_coordinates = polygon.split(", ").map(&:to_f).each_slice(2).to_a
					converted_polygon_coordinates = polygon_coordinates.each_slice(2).map { |slice| slice.each_slice(2).to_a }
					multi_polygon_coordinates << converted_polygon_coordinates
				end

				event.set("[location][type]", "MultiPolygon")
				event.set("[location][coordinates]", multi_polygon_coordinates)
			'
		}
    } else if [type] == "Polygon" {
        ruby {
            code => '
				# Récupérer les coordonnées de la chaîne en supprimant les crochets et en divisant à chaque virgule
				coordinates_string = event.get("coordinates").gsub(/[\[\]]/, "").split(",")

				# Convertir chaque paire de coordonnées (longitude, latitude) en nombres flottants
				coordinates = coordinates_string.each_slice(2).map { |pair| pair.map(&:to_f) }

				# Créer la structure du document pour le champ geo_shape
				event.set("[location][type]", "Polygon")
				event.set("[location][coordinates]", [coordinates])
			'
        }
    }
    
	mutate {
		remove_field => [ "type", "coordinates", "message", "host", "@version", "path", "event", "log", "[event][original]", "[log][file][path]", "[event]", "[log]"]
	}

}
output {
		elasticsearch {
			hosts => "http://localhost:9200"
			index => "iris_2"
			document_id => "%{CODE_IRIS}"
			timeout => 30
			workers => 1
			doc_as_upsert => true
			action => "update"
		}
#stdout { codec => rubydebug }
}

And of course I have this mapping:

{
    "mappings": {
      "properties": {
        "location": {
          "type": "geo_shape"
        }
      }
    }
  }

If someone can help thanks a lot

Failed how? Do you get an error message? Also, if you add output { stdout { codec => rubydebug } } then what does a failing event look like?

1 Like

Finally simple is better, here is the working code, just a JSON.parse...:

mutate {
        add_field => {
            "[location][type]" =>  "%{type}"
        }
    }
	ruby {
		code => "
			require 'json'
			event.set('[location][coordinates]', JSON.parse(event.get('coordinates')))
		"
	}

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