write down,forget
adidas eqt support ultra primeknit vintage white coming soon adidas eqt support ultra boost primeknit adidas eqt support ultra pk vintage white available now adidas eqt support ultra primeknit vintage white sz adidas eqt support ultra boost primeknit adidas eqt adv support primeknit adidas eqt support ultra boost turbo red white adidas eqt support ultra boost turbo red white adidas eqt support ultra boost turbo red adidas eqt support ultra whiteturbo adidas eqt support ultra boost off white more images adidas eqt support ultra boost white tactile green adidas eqt support ultra boost beige adidas eqt support ultra boost beige adidas eqt support refined camo drop adidas eqt support refined camo drop adidas eqt support refined running whitecamo adidas eqt support 93 primeknit og colorway ba7506 adidas eqt running support 93 adidas eqt support 93

ElasticSearch不同类型下同名字段排序错误

<Category: Diving Into ElasticSearch> 查看评论

小异常,记录一把。

虽然之前知道elasticsearch不同类型下同名字段要慎用,并且会出问题,但是只真正碰到了才印象深刻啊,前几天就碰到了,是关于一个排序的问题,事情的经过是这样的,在异常服务重启之后,某个查询突然出问题了,提示信息显示的是排序失败,如下:

事实上这个问题很奇怪,没有动过该索引的任何东西,不过问题出现前倒是动了下服务器,重启了ES,结果第二天就出了这个问题,看来服务端有些问题。
拿到数据,一顿调试之后发现问题了。
该索引xxx下存在不同类型的相同字段名,并且悲催的是类型不一样,原因是后面新加了两个类型,由于是动态创建的,造成了和已存在的同名字段类型的不一致,(已存在的为DateTime类型,自动创建的是String类型)

在构建查询的时候,如果有排序的条件,会调用\SortParseElement.java类里面的addSortField方法,在

这句,会根据字段的名称来获取对应的FieldMappper,如String类型对应的Mapper为StringFieldMapper,DateTime类型的Mapper为LongFieldMapper,然后会选择不同的FieldDataLoader,因为不同类型存储在lucene格式是不一样的,所以如果loader类型不对,加载的数据就解析不到正确的类型(可以理解为反序列化),如下图,同名字段出现了多个定义,通过字段名拿mapping定义的时候,非常朴实的就拿了第一个,而不是我期望的,

然后数据就不对了,当做string来处理,并且认为该字段包含了多个值,调用到了错误的StringOrdValFieldDataComparator类,并且在setNextReader这个方法里面直接抛异常了

这个问题只有在需要排序的时候出现,并且只在拿到错误的的field mapping的时候才会出现,非常隐蔽,需要特别注意哦。

ES在多类型下的同名字段的处理,确实有些问题,但也确实不好处理,如果要支持多个类型的搜索,除非条件中明确包含了是在那个类型下,这样ES才好判断具体应该取那个mapping,当然ES最好在已经明确类型的情况下,应该选择合适的Mapping(回头向shay吐吐槽),所以最好的方法就是避免同名,否则一定要保证类型一致。

本文来自: ElasticSearch不同类型下同名字段排序错误