我在我的应用程序中使用了grails elasticsearch
插件,而且我遇到了一个奇怪的例外。
我有一种使用geo_distance
过滤器构建请求的方法:
def activityList = ElasticSearchService.search(
[types:[DomainA, DomainB],
sort: orderBy, order: orderAs, size: (int)maxRes],
{
// bla bla bla some working closure building a working query
}
if(centerLat != -1){
filter{
geo_distance(
'distance': searchRadius,
'activityLocation': [lat: (Double)centerLat, lon: (Double)centerLon]
)
}
}
}
)
每当我尝试将该方法与过滤器一起使用时(例如,当我将searchRadius
设置为'5km'
和centerLat
/ centerLon
以更正坐标时,我的ElasticSearch
节点变得疯狂,并一直记录以下错误,直到我关闭它:
| Error 2014-08-27 10:31:49,076 [elasticsearch[Agent Zero][bulk][T#2]] ERROR index.IndexRequestQueue - Failed bulk item: MapperParsingException[failed to parse]; nested: ElasticsearchParseException[field must be either 'lat', 'lon' or 'geohash'];
我试着浏览一下这个MappingParserException
被抛出的原因,最后我查看了org.elasticsearch.common.geo.GeoUtils
类的source code。 Apparenty,抛出异常是因为我的lat
和lon
字段不是数字(请参阅第372
行和381
行)。
为什么会这样?我是否声明我的过滤器错误了?
答案 0 :(得分:0)
我认为你的索引类型映射存在问题,为了理解你要发布索引的数据示例和类型映射的问题是什么(你可以从主机获取当前的映射:port / {索引} / _映射/ {类型})。 尝试按照此处的说明定义映射:http://noamt.github.io/elasticsearch-grails-plugin/guide/mapping.html查看3.3.2 GeoPoint,确保正确定义数据点。
答案 1 :(得分:0)
假设activityLocation的映射是" geo_point"那么你不应该用" lat"来表示你的coordindate。和" lon"并且应该能够发送
'activityLocation': [(Double)centerLat,(Double)centerLon]
我认为这是" lat" " LON"在早期版本中,preface可能已被支持为geo_point格式,但从1.0.0开始,我不认为它仍然存在。
答案 2 :(得分:0)
已经有一段时间了,这个问题让我感到很紧张,但我终于解决了。
我正在以这种方式映射以下类:
class A{
static searchable={
activityLocation geoPoint:true, component:true
// some other mappings on some other fields
}
Location activityLocation
// some other fields
}
a
class Location{
static searchable = true
String locationName
Double lat
Double lon
}
有两个问题:
在映射我的root false
对象时,我不想使用activityLocation
选项,因为我希望能够直接搜索它们,这导致我的{{1} }对象包含以下属性(请注意A
字段的存在):
id
不是'activityLocation' : { 'id':'1', 'locationName' : 'foo', 'lat': '42.5464', 'lon': '65.5647' }
,因为它不仅仅包含geoPoint
和lat
字段。
lon
属性映射为locationName
个对象的一部分,这使得不 activityLocation
。我最终通过将映射更改为geoPoint
的以下值来解决问题:
activityLocation
这解决了我的问题,从那时起我的搜索进展顺利。
我必须补充一点,我对这方面的文档感到非常困惑,我有点失望,因为我无法映射具有更多属性的ActivityLocation{
static searchable = {
only = ['lat', 'lon']
root false
}
String locationName
Double lat
Double lon
}
。我希望映射中还有其他字段。
此外,我希望插件能让我更好地访问ES日志,我花了一些时间来找出查找错误代码的位置。
答案 3 :(得分:0)
I have managed to fix this with few lines of coded added to "DeepDomainClassMarshaller.groovy" and overriding this file.
Previous code:-
if (DomainClassArtefactHandler.isDomainClass(propertyClass)) {
String searchablePropertyName = getSearchablePropertyName()
if (propertyValue.class."$searchablePropertyName") {
// todo fixme - will throw exception when no searchable field.
marshallingContext.lastParentPropertyName = prop.name
marshallResult += [(prop.name): ([id: propertyValue.ident(), 'class': propertyClassName] + marshallingContext.delegateMarshalling(propertyValue, propertyMapping.maxDepth))]
} else {
marshallResult += [(prop.name): [id: propertyValue.ident(), 'class': propertyClassName]]
}
// Non-domain marshalling
}
New Code:-
if (DomainClassArtefactHandler.isDomainClass(propertyClass)) {
String searchablePropertyName = getSearchablePropertyName()
if (propertyValue.class."$searchablePropertyName") {
// todo fixme - will throw exception when no searchable field.
marshallingContext.lastParentPropertyName = prop.name
if(propertyMapping?.isGeoPoint())
marshallResult += [(prop.name): (marshallingContext.delegateMarshalling(propertyValue, propertyMapping.maxDepth))]
else
marshallResult += [(prop.name): ([id: propertyValue.ident(), 'class': propertyClassName] + marshallingContext.delegateMarshalling(propertyValue, propertyMapping.maxDepth))]
} else {
marshallResult += [(prop.name): [id: propertyValue.ident(), 'class': propertyClassName]]
}
// Non-domain marshalling
}
Let me know in case issue still persists.
Note:- I am still using elasticsearch:0.0.3.3.