我需要实现一个旨在使用位置过滤我的搜索查询之一的解决方案。您将在这里找到我的实体以及我如何使用@Spatial注释:
@Entity
@Indexed
@Spatial(spatialMode = SpatialMode.RANGE)
@Table(name = "ORGANIZATION", uniqueConstraints = { @UniqueConstraint(columnNames = { "CODE" }) })
public class Organization implements Serializable, FileEntity {
...
@Latitude
@Column(name = "LATITUDE")
private Double latitude;
@Longitude
@Column(name = "LONGITUDE")
private Double longitude;
...
}
索引没有发现任何错误,这是我使用elasticsearch查询找到的结果:
GET http://localhost:9201/com.supralog.lexis.model.organization.organization
{
"com.supralog.lexis.model.organization.organization" : {
"aliases" : { },
"mappings" : {
"com.supralog.lexis.model.organization.Organization" : {
"properties" : {
"_hibernate_default_coordinates" : {
"properties" : {
"lat" : {
"type" : "float"
},
"lon" : {
"type" : "float"
}
}
},
...
}
}
}
}
GET http://localhost:9201/com.supralog.lexis.model.organization.organization/_search?from=0&size=1
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 15628,
"max_score" : 1.0,
"hits" : [
{
"_index" : "com.supralog.lexis.model.organization.organization",
"_type" : "com.supralog.lexis.model.organization.Organization",
"_id" : "...",
"_score" : 1.0,
"_source" : {
...
"_hibernate_default_coordinates" : {
"lat" : 49.1886203,
"lon" : -0.38740259999997306
},
...
}
}
]
}
}
检查索引是否正常后,我尝试查询给定半径100km之内的所有Organization对象:
final Coordinates coordinates = Point.fromDegrees(form.getLatitude(), form.getLongitude());
final String search = StringUtils.join(terms, " ");
final FullTextSession fullTextSession = Search.getFullTextSession(sessionFactory.getCurrentSession());
final QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder()
.forEntity(Organization.class).get();
final org.apache.lucene.search.Query elasticQuery = queryBuilder.spatial().within(100,Unit.KM).ofCoordinates(coordinates).createQuery();
final FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(elasticQuery, Organization.class);
fullTextQuery.setMaxResults(form.getMaximumNumberOfResult());
fullTextQuery.setProjection(FullTextQuery.THIS, FullTextQuery.SCORE);
我的问题在这里,当我尝试执行此查询时,我有以下return语句:
Request: POST /com.supralog.lexis.model.organization.organization/_search with parameters {from=0, size=50}
Response: 400 'Bad Request' with body
{
"error": {
"root_cause": [
{
"type": "query_shard_exception",
"reason": "failed to find geo_point field [_hibernate_default_coordinates]",
"index_uuid": "phOfJTOyRvetHyZrfeUmrA",
"index": "com.supralog.lexis.model.organization.organization"
}
],
"type": "search_phase_execution_exception",
"reason": "all shards failed",
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "com.supralog.lexis.model.organization.organization",
"node": "9DCzSp6kS5KGtMq6tzywzg",
"reason": {
"type": "query_shard_exception",
"reason": "failed to find geo_point field [_hibernate_default_coordinates]",
"index_uuid": "phOfJTOyRvetHyZrfeUmrA",
"index": "com.supralog.lexis.model.organization.organization"
}
}
]
},
"status": 400
}
要解决此问题,我尝试将名称设置为@Spatial记录,尝试使我的实体实现坐标,等等。但是,我总是得到相同的结果。看来hibernate-search没有将我的位置索引为geo_point,这是为什么它在查询中失败的原因...
您对我在文档中错过的内容有任何想法吗?
使用的版本::休眠:5.3;休眠搜索:5.10; elasticsearch:5.6
答案 0 :(得分:0)
Elasticsearch映射错误:
"com.supralog.lexis.model.organization.Organization" : {
"properties" : {
"_hibernate_default_coordinates" : {
"properties" : {
"lat" : {
"type" : "float"
},
"lon" : {
"type" : "float"
}
}
},
...
}
}
“ _ hibernate_default_coordinates”下有一个“属性”属性,这意味着“ _hibernate_default_coordinates”属于“对象”类型,而应属于“ geo_point”类型。
最可能的解释是,您没有在索引编制之前生成架构,Elasticsearch尝试根据收到的文档即时自动生成它。如您所见,这是一个非常糟糕的主意,因为Elasticsearch猜测模式错误的风险非常高。
您应该看看documentation about configuration。特别是,您应该选择合适的index schema management strategy。
简而言之,将以下内容放入hibernate.properties
在开发环境中:Hibernate Search会尽力而为,但是可能会失败,并且数据也不会神奇地重新索引,您必须自己动手
hibernate.search.default.elasticsearch.index_schema_management_strategy update
在生产环境中:您必须自己仔细更新架构,并在更新应用程序时计划mass reindexing。
hibernate.search.default.elasticsearch.index_schema_management_strategy create