ansj分词器和solr结合的零零碎碎
程序员文章站
2024-01-18 17:26:28
...
在solr4.8使用的章节里我讲了很多有关ansj分词器的用法以及相关描述和个人看法。这里新开一篇专门描述。
传送门:https://github.com/ansjsun/ansj_seg/
作者是个年轻的技术男,github上有他的微博,可以和他沟通交流问题(加粉吧,虽然微博现在不流行了,但是这么好的分词器的作者才800多粉丝看着心疼)。
ansj最新版下载下来有40+MB,不过新特性自然语言方面用到的crf.model(NlpAnalysis分词会用到)占了37MB,一般做搜索的是用不到的,所以直接精简掉吧,立刻很轻松有木有。去掉之后就不能再用NlpAnalysis分词了,不过因为分词器通常和索引以及搜索混合使用,建议用ToAnalysis即可。
ansj附加词库是比较前卫的树形添加,按照文件或者文件夹批量添加,这样会带来一个问题,词库是在项目内还是另外存放,在项目内的话,打包项目后不方便找到,有时会有bug,这里我是推荐另外存放,也方便持续添加,然后用配置文件来指向目录即可。开发中善用配置文件可以明显得提高生产力,避免将配置写死在代码里。
如果只用一种分词方法来实现索引和搜索,那么重写Tokenizer即可,但是实际使用solr过程中,索引我们通常希望最小颗粒,搜索采用智能分词,所以就需要传入参数进行配置选择特定的分词器,因此需要重写TokenizerFactory,传入参数。我的schema.xml配置如下
<fieldType name="text_ansj" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="org.ansj.solr.ANSJTokenizerFactory" useSmart="false"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.ansj.solr.ANSJTokenizerFactory" useSmart="true"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true"/>
</analyzer>
</fieldType>
考虑到ansj自己并没有停用词库,后续应该会添加lucene自己的停用词库。重写Tokenizer时需要注意termAtt和offsetAtt设置不要出错,因为ansj的Term没有末位位置,所以需要自己处理:
termAtt.copyBuffer(term.getName().toCharArray(),0,term.getName().length());
offsetAtt.setOffset(term.getOffe(),term.getOffe()+term.getName().length());
前段时间ansj结合solr4.8后一直在做solrcloud,后来直接拿来用,发来ansj有不少问题和不足。一个很大的bug是它索引排序有问题,导致useFastVectorHighlighter时候会报错,无法使用。这个一个不小的问题。我折腾很久,甚至差点放弃了ansj,最后总算发现是ansj的IndexAnalysis有不够周全的地方。毕竟ansj的分词重点是智能分词和发现新词,传统分词不被作者重视也在情理之中。下面说下问题具体所在。
比如我们要对“创业者创业”进行分词,传统的IKanalyzer之类的分词,分出来是“创业者 创业 业者 创业”,ansj分词是“创业者 创业 创 创业 业 者”。先不说创业者被过分细碎分词(ansj实在太简单粗暴了),这个分出来的词排序明显不对,position位置错误,useFastVectorHighlighter高亮会存储错误的向量地址。所以需要在IndexAnalysis里矫正分词的排序。
然后是最细分词的问题,抽时间我会进行二次开发,提高准确度,降低冗余。
未完待续....
传送门:https://github.com/ansjsun/ansj_seg/
作者是个年轻的技术男,github上有他的微博,可以和他沟通交流问题(加粉吧,虽然微博现在不流行了,但是这么好的分词器的作者才800多粉丝看着心疼)。
ansj最新版下载下来有40+MB,不过新特性自然语言方面用到的crf.model(NlpAnalysis分词会用到)占了37MB,一般做搜索的是用不到的,所以直接精简掉吧,立刻很轻松有木有。去掉之后就不能再用NlpAnalysis分词了,不过因为分词器通常和索引以及搜索混合使用,建议用ToAnalysis即可。
ansj附加词库是比较前卫的树形添加,按照文件或者文件夹批量添加,这样会带来一个问题,词库是在项目内还是另外存放,在项目内的话,打包项目后不方便找到,有时会有bug,这里我是推荐另外存放,也方便持续添加,然后用配置文件来指向目录即可。开发中善用配置文件可以明显得提高生产力,避免将配置写死在代码里。
如果只用一种分词方法来实现索引和搜索,那么重写Tokenizer即可,但是实际使用solr过程中,索引我们通常希望最小颗粒,搜索采用智能分词,所以就需要传入参数进行配置选择特定的分词器,因此需要重写TokenizerFactory,传入参数。我的schema.xml配置如下
<fieldType name="text_ansj" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="org.ansj.solr.ANSJTokenizerFactory" useSmart="false"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.ansj.solr.ANSJTokenizerFactory" useSmart="true"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true"/>
</analyzer>
</fieldType>
考虑到ansj自己并没有停用词库,后续应该会添加lucene自己的停用词库。重写Tokenizer时需要注意termAtt和offsetAtt设置不要出错,因为ansj的Term没有末位位置,所以需要自己处理:
termAtt.copyBuffer(term.getName().toCharArray(),0,term.getName().length());
offsetAtt.setOffset(term.getOffe(),term.getOffe()+term.getName().length());
前段时间ansj结合solr4.8后一直在做solrcloud,后来直接拿来用,发来ansj有不少问题和不足。一个很大的bug是它索引排序有问题,导致useFastVectorHighlighter时候会报错,无法使用。这个一个不小的问题。我折腾很久,甚至差点放弃了ansj,最后总算发现是ansj的IndexAnalysis有不够周全的地方。毕竟ansj的分词重点是智能分词和发现新词,传统分词不被作者重视也在情理之中。下面说下问题具体所在。
比如我们要对“创业者创业”进行分词,传统的IKanalyzer之类的分词,分出来是“创业者 创业 业者 创业”,ansj分词是“创业者 创业 创 创业 业 者”。先不说创业者被过分细碎分词(ansj实在太简单粗暴了),这个分出来的词排序明显不对,position位置错误,useFastVectorHighlighter高亮会存储错误的向量地址。所以需要在IndexAnalysis里矫正分词的排序。
然后是最细分词的问题,抽时间我会进行二次开发,提高准确度,降低冗余。
未完待续....