Как проиндексировать файл geojson в elasticsearch?

#elasticsearch #geojson #shapefile

#elasticsearch #geojson #шейп-файл

Вопрос:

Я пытаюсь сохранить пространственные данные в виде geojson, файлов CSV и файлов формы в elasticsearch С ИСПОЛЬЗОВАНИЕМ PYTHON.Я новичок в elasticsearch и даже после ознакомления с документацией я не могу успешно его проиндексировать. Будем признательны за любую помощь.

пример файла geojson :

 {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "ID_0": 105,
        "ISO": "IND",
        "NAME_0": "India",
        "ID_1": 1288,
        "NAME_1": "Telangana",
        "ID_2": 15715,
        "NAME_2": "Telangana",
        "VARNAME_2": null,
        "NL_NAME_2": null,
        "HASC_2": "IN.TS.AD",
        "CC_2": null,
        "TYPE_2": "State",
        "ENGTYPE_2": "State",
        "VALIDFR_2": "Unknown",
        "VALIDTO_2": "Present",
        "REMARKS_2": null,
        "Shape_Leng": 8.103535,
        "Shape_Area": 127258717496
      },
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              79.14429367552918,
              19.500257885106404
            ],
            [
              79.14582245808431,
              19.498859172536427
            ],
            [
              79.14600496956801,
              19.498823981691853
            ],
            [
              79.14966523737327,
              19.495821705263914
            ]
          ]
        ]
      }
    }
  ]
}
  

Комментарии:

1. Можете ли вы показать свой файл geojson? (или его часть)

2. {«type»: «FeatureCollection», «features»: [{«тип»:»Функция», «properties»:{«ID_0″:105,»ISO»:»IND»,»NAME_0″:»India»,»ID_1″:1288,»NAME_1″:»Telangana»,»ID_2″:15715,»NAME_2″:»Telangana»,»VARNAME_2″:null,»NL_NAME_2″:null,»HASC_2″:»IN.TS.AD»,»CC_2″:null,»TYPE_2″:»State»,»ENGTYPE_2″:»State»,»VALIDFR_2″:»Unknown»,»VALIDTO_2″:»Present»,»REMARKS_2″:null,»Shape_Leng»:8.103535,»Shape_Area»:127258717496},»geometry»:{«type»:»Polygon»,»coordinates»:[[[79.14429367552918,19.500257885106404],[79.14582245808431,19.498859172536427],[79.14600496956801,19.498823981691853],

3. Пожалуйста, обновите свой вопрос с его помощью

4. Забавно, я только что прочитал документацию по elasticsearch.co и действительно, в главе «Как проиндексировать файл geosjon …» показан только документ geojson, но не то, как его проиндексировать.

5. @intern ты когда-нибудь это понимал?

Ответ №1:

Код

 import geojson
from datetime import datetime
from elasticsearch import Elasticsearch, helpers


def geojson_to_es(gj):

    for feature in gj['features']:

        date = datetime.strptime("-".join(feature["properties"]["event_date"].split('-')[0:2])   "-"   feature["properties"]["year"], "%d-%b-%Y")
        feature["properties"]["timestamp"] = int(date.timestamp())
        feature["properties"]["event_date"] = date.strftime('%Y-%m-%d')
        yield feature


with open("GeoObs.json") as f:
    gj = geojson.load(f)

    es = Elasticsearch(hosts=[{'host': 'localhost', 'port': 9200}])

    k = ({
        "_index": "YOUR_INDEX",
        "_source": feature,
    } for feature in geojson_to_es(gj))

    helpers.bulk(es, k)
  

Объяснение

 with open("GeoObs.json") as f:
    gj = geojson.load(f)

    es = Elasticsearch(hosts=[{'host': 'localhost', 'port': 9200}])
  

Эта часть кода загружает внешний файл geojson, затем подключается к Elasticsearch.

     k = ({
        "_index": "conflict-data",
        "_source": feature,
    } for feature in geojson_to_es(gj))

    helpers.bulk(es, k)
  

() s здесь создает генератор, который мы будем передавать helpers.bulk(es, k) . Помните _source , что исходные данные такие же, как в Elasticsearch, то есть: наш необработанный JSON. _index это просто индекс, в который мы хотим поместить наши данные. Вы увидите другие примеры с _doc здесь. Это часть типов сопоставления и больше не существует в Elasticsearch 7.X .

 def geojson_to_es(gj):

    for feature in gj['features']:

        date = datetime.strptime("-".join(feature["properties"]["event_date"].split('-')[0:2])   "-"   feature["properties"]["year"], "%d-%b-%Y")
        feature["properties"]["timestamp"] = int(date.timestamp())
        feature["properties"]["event_date"] = date.strftime('%Y-%m-%d')
        yield feature
  

Функция geojson использует генератор для создания событий. Функция генератора будет вместо возврата и завершения resume at the keyword выдавать` после каждого вызова. В этом случае мы генерируем наши функции GeoJSON. В моем коде вы также видите:

 date = datetime.strptime("-".join(feature["properties"]["event_date"].split('-')[0:2])   "-"   feature["properties"]["year"], "%d-%b-%Y")
feature["properties"]["timestamp"] = int(date.timestamp())
feature["properties"]["event_date"] = date.strftime('%Y-%m-%d')
  

Это всего лишь пример манипулирования данными в JSON перед отправкой их в Elasticsearch.

Ключ находится в вашем файле сопоставления, у вас должно быть что-то помечено как geo_point или geo_shape . Эти типы данных — то, как Elasticsearch распознает географические данные. Пример из моего файла сопоставления:

 ...
{
  "properties": {
    "geometry": {
      "properties": {
        "coordinates": {
          "type": "geo_point"
        },
        "type": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    },
...
  

То есть перед загрузкой ваших данных GeoJSON с помощью Python вам необходимо создать свой индекс, а затем применить файл сопоставления, который включает в себя либо geo_shape , либо geo_point используя что-то вроде:

curl -X PUT "localhost:9200/YOUR_INDEX?pretty"
curl -X PUT localhost:9200/YOUR_INDEX/_mapping?pretty -H "Content-Type: application/json" -d @mapping.json

Ответ №2:

Вы должны разделить объекты GeoJSON на (1) геометрию и (2) свойства / атрибуты. части. Вы не можете напрямую индексировать объекты GeoJSON и коллекции объектов (см. Документацию), в качестве типа поля поддерживается только геометрическая часть.

Таким образом, ваш окончательный индексируемый документ будет выглядеть несколько сглаженным:

 {
    "ID_0": 105,
    "ISO": "IND",
    "NAME_0": "India",
    "ID_1": 1288,
    "NAME_1": "Telangana",
    "ID_2": 15715,
    "NAME_2": "Telangana",
    "VARNAME_2": null,
    "NL_NAME_2": null,
    "HASC_2": "IN.TS.AD",
    "CC_2": null,
    "TYPE_2": "State",
    "ENGTYPE_2": "State",
    "VALIDFR_2": "Unknown",
    "VALIDTO_2": "Present",
    "REMARKS_2": null,
    "Shape_Leng": 8.103535,
    "Shape_Area": 127258717496,
    "geometry": {
        "type": "Polygon",
        "coordinates": [
            [
                [
                    79.14429367552918,
                    19.500257885106404
                ],
                [
                    79.14582245808431,
                    19.498859172536427
                ],
                [
                    79.14600496956801,
                    19.498823981691853
                ],
                [
                    79.14966523737327,
                    19.495821705263914
                ]
            ]
        ]
    }
}
  

Комментарии:

1. Ответили давно, но если кто-нибудь читает; Есть ли тип данных для «Shape_Area» или Leng? Я просто использую значение с плавающей точкой / long или Point?

2. Для них нет специального типа — вы должны придерживаться простых числовых типов в ES: elastic.co/guide/en/elasticsearch/reference/current/number.html

3. Как бы вы на самом деле выполнили индексацию данных?