我正在开发一个微服务,用于通过使用spring-data-elasticsearch使用Java / Spring Boot管理位置,并且当尝试使用我的控制器向ES输入新数据时,数据输入未正确映射到ES中的文档,特别是地理位置属性“位置”。
我尝试从导入org.springframework.data.elasticsearch.core.geo.GeoPoint和org.springframework.data.elasticsearch.core.geo.GeoPoint中使用GeoPoint,在两种情况下都不会键入保存到ES的数据作为geo_point
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import io.swagger.annotations.ApiModelProperty;
@Document(indexName = "location", type="location")
public class Location {
@Id
@ApiModelProperty(hidden = true)
private String id;
private String appId;
private String resourceId;
@GeoPointField
private GeoPoint location;
private String street;
private String city;
// more attr and method was ommited
}
当我获得映射数据时,使用ElasticSearchRepository将数据保存到ES中后,显示如下:
{
"location" : {
"mappings" : {
"location" : {
"properties" : {
"appId" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"city" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"country" : {
"properties" : {
"countryCcFips" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"countryCcIso" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"countryName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"location" : {
"properties" : {
"lat" : {
"type" : "float"
},
"lon" : {
"type" : "float"
}
}
},
"parish" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
// ommited more json data
请,我需要将GeoPoint字段(位置)映射到geo_point到ES中,这对于正确执行Geoqueries非常重要。
我正在使用Spring Data ElasticSearch和Spring Boot 2.1.3.RELEASE和ElasticSearch驱动程序6.4.3和ElasticSearch Server 6.4
答案 0 :(得分:0)
我创建了一个带有存储库,控制器的最小应用程序,并使用Spring Boot 2.1.3.RELEASE,Spring Data Elasticsearch 3.1.5.RELEASE,elasticsearch客户端6.4.3和Elasticsearch服务器6.4.0来运行它。
我使用的Person
pojo类具有两个geo_point字段,一个是普通弹簧GeoPoint
,一个是使用MyGeoPoint
注释的自定义GeoPointField
。 / p>
启动应用程序并通过调用RestController的init
方法插入一条记录后,索引中的映射就可以了:
{
"person": {
"aliases": {},
"mappings": {
"person": {
"properties": {
"firstName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"geoPoint": {
"type": "geo_point"
},
"id": {
"type": "long"
},
"lastName": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"myGeoPoint": {
"type": "geo_point"
}
}
}
},
"settings": {
"index": {
"refresh_interval": "1s",
"number_of_shards": "5",
"provided_name": "person",
"creation_date": "1554750620775",
"store": {
"type": "fs"
},
"number_of_replicas": "1",
"uuid": "w1L279wOQUmvDPMu4iYXtg",
"version": {
"created": "6040099"
}
}
}
}
}
Person.java
/*
* (c) Copyright 2019 sothawo
*/
package com.sothawo.springdataelastictest;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.GeoPointField;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
/**
* @author P.J. Meisch (pj.meisch@sothawo.com)
*/
@Document(indexName = "person", type = "person")
public class Person {
@Id private Long id;
private String lastName;
private String firstName;
private GeoPoint geoPoint;
@GeoPointField private MyGeoPoint myGeoPoint;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public GeoPoint getGeoPoint() {
return geoPoint;
}
public void setGeoPoint(GeoPoint geoPoint) {
this.geoPoint = geoPoint;
}
public MyGeoPoint getMyGeoPoint() {
return myGeoPoint;
}
public void setMyGeoPoint(MyGeoPoint myGeoPoint) {
this.myGeoPoint = myGeoPoint;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", lastName='" + lastName + '\'' +
", firstName='" + firstName + '\'' +
", geoPoint=" + geoPoint +
", myGeoPoint=" + myGeoPoint +
'}';
}
public static class MyGeoPoint {
private double lat;
private double lon;
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLon() {
return lon;
}
public void setLon(double lon) {
this.lon = lon;
}
@Override
public String toString() {
return "MyGeoPoint{" + "lat=" + lat + ", lon=" + lon + '}';
}
}
}
PersonRepository.java :
package com.sothawo.springdataelastictest;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface PersonRepository extends ElasticsearchRepository<Person, Long> {}
ElasticsearchRepositoryController.java :
package com.sothawo.springdataelastictest;
import org.springframework.data.elasticsearch.core.geo.GeoPoint;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/repo")
public class ElasticsearchRepositoryController {
private PersonRepository personRepository;
public ElasticsearchRepositoryController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@GetMapping("/init")
public Long initPerson() {
final Person person = new Person();
person.setId(42L);
person.setFirstName("John");
person.setLastName("Doe");
GeoPoint geoPoint = new GeoPoint(12.34, 56.78);
person.setGeoPoint(geoPoint);
Person.MyGeoPoint myGeoPoint = new Person.MyGeoPoint();
myGeoPoint.setLat(43.21);
myGeoPoint.setLon(87.65);
person.setMyGeoPoint(myGeoPoint);
return personRepository.save(person).getId();
}
}
SpringdataElasticTestApplication.java :
package com.sothawo.springdataelastictest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
@SpringBootApplication
@EnableElasticsearchRepositories
public class SpringdataElasticTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringdataElasticTestApplication.class, args);
}
}
所以我找不到此代码和所用版本的问题。您可以使用这些类重现该错误,还是可以构建一个最小化该错误的示例?
您确定映射是由Repository类而非其他地方创建的吗?
您可以在应用程序启动后之后检查映射,但之前是否将任何数据插入索引?
答案 1 :(得分:0)
我有一个类似的问题,但是我是这样解决的: 在ES端,按如下方式创建索引:
PUT my_index
{
"mappings": {
"properties": {
"doc.location": {
"type": "geo_point"
}
}
}
}
在location
中,我要成为geo_point类型的字段。打扰一下我的英语。
当然,ES的持久性必须遵循以下结构:
"location": {
"lat": 41.12,
"lon": -71.34
}
您说过here。
答案 2 :(得分:0)
在我删除应用程序运行期间的索引后,我遇到了同样的问题(spring-boot
2.2.1.RELEASE
和spring-data-elasticserach
4.0.0.DATAES-690-SNAPSHOT
)
保存文档后,索引位置属性的错误映射:
... other properites...
"location" : {
"properties" : {
"lat" : {
"type" : "float"
},
"lon" : {
"type" : "float"
}
}
}
在应用程序运行时无法解决它,映射始终是错误的。
此解决方案对我有用:
现在,索引是使用 Just 位置字段创建的,所有其他字段映射都丢失了。将文档编入索引(使用ElasticSearchRepository.save
后,一切都很好,并添加了其他映射。
{
"properties": {
"location": {
"type": "geo_point"
}
}
}
答案 3 :(得分:0)
我遇到了类似的问题,但是在浏览了一些文档之后,我不得不使用以下代码段来使Elasticsearch将我的GeoPoint
属性创建为geo_point
类型的字段。
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@PostConstruct
public void init() {
IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(PropertySearch.class);
indexOperations.putMapping(indexOperations.createMapping());
indexOperations.refresh();
}
有关更多信息,请参阅post
答案 4 :(得分:-1)
if (elasticsearchRestTemplate.indexOps(MerchantModel.class).exists()) {
elasticsearchRestTemplate.indexOps(MerchantModel.class).delete();
}
// fix geo_point mapping
CreateIndexRequest createIndexRequest = new CreateIndexRequest("merchant");
createIndexRequest.mapping("{\n" +
" \"properties\": {\n" +
" \"location\": {\n" +
" \"type\": \"geo_point\"\n" +
" }\n" +
" }\n" +
" }", XContentType.JSON);
IndicesClient indicesClient = restHighLevelClient.indices();
CreateIndexResponse createIndexResponse = indicesClient.create(createIndexRequest, RequestOptions.DEFAULT);
log.info("create ES merchant mapping:[isAcknowledged={}]", createIndexResponse.isAcknowledged());