如何在Solr枚举类型字段中插入未知值并实现指定排序逻辑
刚好之前处理过类似的Solr自定义排序需求,我来给你拆解下解决方案,分两步搞定:先解决未知值插入报错的问题,再实现你要的排序逻辑。
你之前遇到的插入未知值报错,大概率是因为Status字段用了Solr的EnumFieldType——这个类型会严格校验插入值是否在预定义的枚举列表里,不在就会抛出异常。要允许插入未知值,我们需要把字段类型改成普通的字符串类型,同时开启文档值(docValues)来保证排序性能。
修改你的schema配置(不管是managed-schema还是schema.xml),把Status字段的定义调整为:
<field name="Status" type="string" indexed="true" stored="true" docValues="true"/>
如果之前你用了自定义的枚举字段类型,直接替换掉就行。这样调整后,任何字符串值都能插入到Status字段里,不会再触发异常。
接下来要实现「已知枚举值按指定顺序排列,未知值按字母序排后面」的需求,我们可以用Solr的case函数来给不同的Status值分配排序权重,再结合字段本身的字母序排序。
方式一:查询时直接指定排序规则
在查询的sort参数里使用case函数定义权重,再按权重和字段本身排序:
sort=case(Status, 'CREATED', 1, 'SUBMITTED', 2, 'DELIVERED', 3, 99) asc, Status asc
case函数的逻辑:匹配到CREATED返回1,SUBMITTED返回2,DELIVERED返回3,所有未知值返回99- 先按权重升序:这样已知的三个枚举值会按
CREATED→SUBMITTED→DELIVERED的顺序排在最前面 - 再按
Status字段本身升序:未知值(比如UNKNOWN1、UNKNOWN2)会按字母顺序排在权重为99的组里
如果需要大小写不敏感的字母排序,可以把第二个排序条件改成lowercase(Status) asc:
sort=case(Status, 'CREATED', 1, 'SUBMITTED', 2, 'DELIVERED', 3, 99) asc, lowercase(Status) asc
方式二:用Runtime Field固化排序逻辑
如果不想每次查询都写长长的case语句,可以在schema里定义一个**运行时字段(Runtime Field)**来预先计算排序权重:
<runtimeField name="status_sort_weight" type="int"> <str name="function">case(Status, 'CREATED', 1, 'SUBMITTED', 2, 'DELIVERED', 3, 99)</str> </runtimeField>
之后查询时直接用这个运行时字段排序即可,更简洁:
sort=status_sort_weight asc, Status asc
你可以插入测试数据:CREATED、SUBMITTED、DELIVERED、UNKNOWN1、UNKNOWN2、TEST,用上面的排序参数查询,得到的顺序应该是:CREATED→SUBMITTED→DELIVERED→TEST→UNKNOWN1→UNKNOWN2,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Krishna Gond

