欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

solr排序之根据中文的首字母排序

程序员文章站 2024-02-02 08:40:04
...
这次要分享的是关于近期在工作中的一个业务需求实现
需求-------------------------
    需求很简单,简化来说就是需要对一个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
      },
      {}
    ]
  }