elasticsearch,Grails,elasticsearch" /> elasticsearch,Grails,elasticsearch" />

Grails 带地理距离过滤器的ElasticSearch MapperParsingException n

Grails 带地理距离过滤器的ElasticSearch MapperParsingException n,grails,elasticsearch,Grails,elasticsearch,我在应用程序中使用这个插件,遇到了一个奇怪的异常 我有一种使用geo_distance过滤器构建请求的方法: class A{ static searchable={ activityLocation geoPoint:true, component:true // some other mappings on some other fields } Location activityLocation // some other fields } a class Loca

我在应用程序中使用这个插件,遇到了一个奇怪的异常

我有一种使用
geo_distance
过滤器构建请求的方法:

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
}
def activityList=ElasticSearchService.search(
[类型:[域A,域B],
排序:orderBy,顺序:orderAs,大小:(int)maxRes],
{
//blablabla一些工作闭包构建一个工作查询
}
如果(中心平面!=-1){
滤器{
地理距离(
“距离”:搜索半径,
“活动位置”:[lat:(双)centerLat,lon:(双)centerLon]
)
}
}
}
)
每当我尝试将该方法与过滤器一起使用时(即,当我将例如
searchRadius
设置为
'5km'
centerLat
/
centerLon
以更正坐标时,我的
ElasticSearch
节点会发疯,并不断记录以下错误,直到我关闭它:

| Error 2014-08-27 10:31:49076[elasticsearch[Agent Zero][bulk][T#2]]错误索引.索引请求队列-失败的批量项目:MapperParsingException[未能解析];嵌套:ElasticsearchParseException[字段必须为'lat'、'lon'或'geohash';
我尝试在web上查找引发此
MappingParserException
的原因,最后我查找了
org.elasticsearch.common.geo.GeoUtils
类的异常。显然,引发异常是因为我的
lat
lon
字段不是数字(请参见第372行和第381行)


为什么会发生这种情况?我是否声明我的筛选器错误?

我认为您的索引类型映射有问题,为了理解问题所在,您必须发布一些正在索引的数据和类型映射的示例(您可以从主机获取当前映射:port/{index}/\u-mapping/{type})。
尝试按此处所述定义映射:查看3.3.2 GeoPoint,确保正确定义数据点。

假设activityLocation的映射为“geo_point”,则无需在坐标前加上“lat”和“lon”,只需发送即可

'activityLocation': [(Double)centerLat,(Double)centerLon]

我认为这个“lat”“lon”前言在早期版本中可能作为geo_点格式得到支持,但从1.0.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
}
有两个问题:

  • 我不想在映射我的
    activityLocation
    对象时使用
    root false
    选项,因为我希望能够直接搜索它们,这导致我的
    A
    对象包含以下属性(请注意
    id
    字段的存在):

    'activityLocation':{'id':'1','locationName':'foo','lat':'42.5464','lon':'65.5647'}

  • 它不是
    地质点
    ,因为它不仅仅有
    lat
    lon
    字段

  • 我正在映射
    locationName
    属性,作为我的
    activityLocation
    对象的一部分,这使它们不是
    geoPoint
    s
  • 我最终解决了这个问题,将
    activityLocation
    的映射更改为以下值:

    ActivityLocation{
        static searchable = {
            only = ['lat', 'lon']
            root false
        }
    
        String locationName
    
        Double lat
    
        Double lon
    }
    
    这解决了我的问题,从那时起我的搜索进展顺利

    我必须补充一点,我对文档中关于这一点的内容感到非常困惑,我有点失望,因为我无法映射具有更多属性的
    地质点


    此外,我希望该插件能让我更好地访问ES日志,我花了一段时间才找到错误代码。

    我确实发现了问题所在,我将发布详细的答案,因为我认为文档不是很清楚。事实证明,这确实是一个映射问题,但文档中指出“longitud的字段”e必须被命名为lon,纬度的字段必须被命名为lat',而不是说不能有任何其他字段。参见我的答案。
    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.