solr排序之根据中文的首字母排序
程序员文章站
2024-02-02 08:31:28
...
这次要分享的是关于近期在工作中的一个业务需求实现
需求-------------------------
需求很简单,简化来说就是需要对一个title字段,根据中文拼音的首字母进行排序
实现-------------------------
理所当然的想到直接用solr的sort功能对title desc排序,发现结果不如预期
所以,采用新建一个title_fc的字段,存储title字段的第一个字的拼音首字母,打开docValues=true,对该字段进行排序。
该方法实现也很简单,首先在schema.xml文件中声明一个title_fc字段
以上三行代码就是实现新字段的注册,并将title中的内容copy到新字段中。
FirstCharacter是自己实现的字段类型,继承TrieIntField,将注入的title值,用pinyin4j.jar包翻译为拼音类型,并取首字母的ascii码值,作为新字段的值,再对这个字段进行排序就可以了,实现效果如下。
实现后跟业务沟通发现需求不止需要第一个字的汉字首字母,还需要记录所有字的拼音首字母,从而当第一个字母相同时进行比较后续的字母。
实现这个一开始不知道怎么下手,无法再用ascii的方法记录值,也不能用相加的方法。后来在和百岁沟通后,决定用int的32个bit记录几个值。
具体原理为,例如一个title的值为“二维火”,拼音首字母为ewh,则记录三个字母的ascii码和a的差值,则为5,23,8,对应的二进制的为00101,10101,01000,则用一个int记录就是001011010101000,即5800,每个title进行这种转换,则可以根据每个字母进行转换了。结果如下
需求-------------------------
需求很简单,简化来说就是需要对一个title字段,根据中文拼音的首字母进行排序
实现-------------------------
理所当然的想到直接用solr的sort功能对title desc排序,发现结果不如预期
"response": { "numFound": 7, "start": 0, "docs": [ { "title": "二维火" }, { "title": "a城西银泰" }, { "title": "?桔子里" }, { "title": "1三益里" }, { "title": "/b古翠路" }, { "title": " 翠苑四区" }, {} ] }
所以,采用新建一个title_fc的字段,存储title字段的第一个字的拼音首字母,打开docValues=true,对该字段进行排序。
该方法实现也很简单,首先在schema.xml文件中声明一个title_fc字段
<field name="title_fc" type="first_character" indexed="false" stored="true" docValues="true"/> <fieldType name="first_character" class="com.dfire.fieldtype.FirstCharacter" precisionStep="0" positionIncrementGap="0"/> <copyField source="title" dest="title_fc"/>
以上三行代码就是实现新字段的注册,并将title中的内容copy到新字段中。
FirstCharacter是自己实现的字段类型,继承TrieIntField,将注入的title值,用pinyin4j.jar包翻译为拼音类型,并取首字母的ascii码值,作为新字段的值,再对这个字段进行排序就可以了,实现效果如下。
"response": { "numFound": 7, "start": 0, "docs": [ { "title": "/b古翠路", "title_fc": 126 }, { "title": "?桔子里", "title_fc": 126 }, { "title": "二维火", "title_fc": 101 }, { "title": " 翠苑四区", "title_fc": 99 }, { "title": "a城西银泰", "title_fc": 97 }, { "title": "1三益里", "title_fc": 49 }, {} ] }
实现后跟业务沟通发现需求不止需要第一个字的汉字首字母,还需要记录所有字的拼音首字母,从而当第一个字母相同时进行比较后续的字母。
实现这个一开始不知道怎么下手,无法再用ascii的方法记录值,也不能用相加的方法。后来在和百岁沟通后,决定用int的32个bit记录几个值。
具体原理为,例如一个title的值为“二维火”,拼音首字母为ewh,则记录三个字母的ascii码和a的差值,则为5,23,8,对应的二进制的为00101,10101,01000,则用一个int记录就是001011010101000,即5800,每个title进行这种转换,则可以根据每个字母进行转换了。结果如下
"response": { "numFound": 7, "start": 0, "docs": [ { "title": "1三益里", "testfield": 474845952 }, { "title": "?桔子里", "testfield": 371827456 }, { "title": "/b古翠路", "testfield": 369651916 }, { "title": "二维火", "testfield": 89948160 }, { "title": " 翠苑四区", "testfield": 56964160 }, { "title": "a城西银泰", "testfield": 17663572 }, {} ] }
上一篇: 简单说说PHP优化那些事(经验分享)