Spring Data Elasticsearch с ES 7.2.1 | Ошибка отображения GeoPoint при индексации - PullRequest
0 голосов
/ 14 апреля 2020

Я использую ES 7.2.1 для хранения большого количества данных, основанных на местоположении, и запрашиваю близлежащие местоположения. Для координат местоположения я использую поля GeoPoint из моей java кодовой базы.

ES: 7.2.1
Spring Data Elasticsearch: 4.0.0.DATAES-690 -SNAPSHOT
MVN org.elasticsearch: 7.2.1

Шаблон:

curl -X PUT "localhost:9200/_template/store_locator_template?pretty"
{
  "order": 1,
  "index_patterns": [
    "store_locator_*"
  ],
  "settings": {
  },
  "mappings": {
      "properties": {
      "esId": {
        "type": "keyword"
      },
      "geoPoint": {
        "type": "geo_point"
      },
      "storeName": {
        "type": "keyword"
      }
    }
  }
}

При попытке вставить данные с помощью bulkIndex (), I получаю эту ошибку:

org.springframework.data.elasticsearch.ElasticsearchException: 
Bulk indexing has failures. Use ElasticsearchException.getFailedDocuments() 
for detailed messages [{QObQeXEBqxAg6uMFyeNZ=ElasticsearchException
[Elasticsearch exception 
[type=illegal_argument_exception, reason=
mapper [geoPoint] of different type, 
current_type [geo_point], merged_type [ObjectMapper]]]}]

Сущность:

@Getter
@Setter
@ToString
@EqualsAndHashCode(of = "esId", callSuper = false)
@NoArgsConstructor
@Document(indexName = "store_locator_index", replicas = 0, createIndex = false)
public class EsEntity {

  @Id
  @Field(type = FieldType.Text)
  private String esId;

  @GeoPointField
  private GeoPoint geoPoint;

  @Field(type = FieldType.Text)
  private String storeName;
}

ОБНОВЛЕНИЕ: Если я использую приведенный ниже код, он работает нормально. он устанавливает соответствие как требуется, и данные пружины es не жалуются!

//clazz -> entity class with @Document annotation

boolean indexCreated = false;
if (!elasticsearchOperations.indexExists(clazz)) {
    indexCreated = elasticsearchOperations.createIndex(clazz);
}
if (indexCreated) {
    elasticsearchOperations.refresh(clazz);
    elasticsearchOperations.putMapping(clazz);   --> Does the MAGIC
}

... И отображение, генерируемое из приведенного выше кода:

{
   "esentity":{              ---> Why is this here??
      "properties":{
         "esId":{
            "type":"keyword",
            "index":true
         },
         "geoPoint":{
            "type":"geo_point"
         }
      }
   }
}

Это добавляет тип по имени моего класса сущностей, к отображению!

==========================
Также .....

Кажется, все работает для:
ES: 6.4.3
Spring Data Elasticsearch: 3.1.X

Я могу (через шаблон) вставить документ с полем GeoPoint. Индекс генерируется автоматически, когда do c вставляется через код. Тот же набор кода работает без ошибок !!!!

Вот мой шаблон:

curl -X PUT "localhost:9200/_template/store_locator_template?pretty"
{
  "order": 1,
  "index_patterns": [
    "store_locator_*"
  ],
  "settings": {
  },
  "mappings": {
    "store_locator_index": {
      "properties": {
      "esId": {
        "type": "keyword"
      },
      "geoPoint": {
        "type": "geo_point"
      },
      "storeName": {
        "type": "keyword"
      }
    }
   }
  }
}

Вот отображение:

{
  "mapping": {
    "properties": {
      "esId": {
        "type": "keyword"
      },
      "geoPoint": {
        "type": "geo_point"
      }
    }
  }
}

1 Ответ

0 голосов
/ 17 апреля 2020

В отображаемом коде есть некоторые вещи, которые не совпадают:

В первом отображаемом шаблоне вы определяете storeName типа keyword, но на объекте у вас есть тип text.

Поле, помеченное @Id, всегда имеет тип keyword, аннотация @Field, определяющая его как тип text, игнорируется.

Я использовал следующие версии: ES 7.3 .0 (на моем компьютере нет 7.2.1), текущий мастер Spring Data 4.0, клиентские библиотеки установлены на 7.3.0.

Когда шаблон не определен, но создаю индекс с помощью код, который вы показали:

    boolean indexCreated = false;

    Class<EsEntity> clazz = EsEntity.class;
    if (!elasticsearchOperations.indexExists(clazz)) {
        indexCreated = elasticsearchOperations.createIndex(clazz);
    }
    if (indexCreated) {
        elasticsearchOperations.refresh(clazz);
        elasticsearchOperations.putMapping(clazz);
    }

Я получаю следующий индекс:

{
  "store_locator_index": {
    "aliases": {},
    "mappings": {
      "properties": {
        "esId": {
          "type": "keyword"
        },
        "geoPoint": {
          "type": "geo_point"
        },
        "storeName": {
          "type": "text"
        }
      }
    },
    "settings": {
      "index": {
        "refresh_interval": "1s",
        "number_of_shards": "1",
        "provided_name": "store_locator_index",
        "creation_date": "1587073075464",
        "store": {
          "type": "fs"
        },
        "number_of_replicas": "0",
        "uuid": "72aZqWDtS7KLDMwdkgVtag",
        "version": {
          "created": "7030099"
        }
      }
    }
  }
}

Отображение выглядит так, как должно, в отображении есть информация типа no (это было написано версией Spring Data Elasticsearch 3.2 при использовании ES 6, но я больше не использовал)

Когда я добавляю показанный вами шаблон, а затем выполняю массовую вставку со следующим кодом:

    EsEntity es1 = new EsEntity();
    es1.setEsId("1");
    es1.setGeoPoint(new GeoPoint(12, 34));
    es1.setStoreName("s1");
    IndexQuery query1 = new IndexQueryBuilder().withId("1").withObject(es1).build();

    EsEntity es2 = new EsEntity();
    es2.setEsId("2");
    es2.setGeoPoint(new GeoPoint(56, 78));
    es2.setStoreName("s2");
    IndexQuery query2 = new IndexQueryBuilder().withId("2").withObject(es2).build();

    elasticsearchOperations.bulkIndex(Arrays.asList(query1, query2), IndexCoordinates.of("store_locator_index"));

, затем создается следующий индекс (обратите внимание, что store_name теперь имеет тип keyword, исходя из шаблона):

{
  "store_locator_index": {
    "aliases": {},
    "mappings": {
      "properties": {
        "_class": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "esId": {
          "type": "keyword"
        },
        "geoPoint": {
          "type": "geo_point"
        },
        "storeName": {
          "type": "keyword"
        }
      }
    },
    "settings": {
      "index": {
        "creation_date": "1587073540386",
        "number_of_shards": "1",
        "number_of_replicas": "1",
        "uuid": "LqzXMC5uRmKmImIzblFBOQ",
        "version": {
          "created": "7030099"
        },
        "provided_name": "store_locator_index"
      }
    }
  }
}

и два документа вставляются в том порядке, в каком они должны:

{
  "took": 22,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "store_locator_index",
        "_type": "_doc",
        "_id": "1",
        "_score": 1.0,
        "_source": {
          "_class": "com.sothawo.springdataelastictest.EsEntity",
          "esId": "1",
          "geoPoint": {
            "lat": 12.0,
            "lon": 34.0
          },
          "storeName": "s1"
        }
      },
      {
        "_index": "store_locator_index",
        "_type": "_doc",
        "_id": "2",
        "_score": 1.0,
        "_source": {
          "_class": "com.sothawo.springdataelastictest.EsEntity",
          "esId": "2",
          "geoPoint": {
            "lat": 56.0,
            "lon": 78.0
          },
          "storeName": "s2"
        }
      }
    ]
  }
}

Так что я не могу найти ошибку в коде, но вы должны проверить те mplates и существующие индексы, если есть конфликтующие записи.

...