solr 中文分词 mmseg4j 使用例子

mmseg4j 第一个版本就可以方便地与 solr 集成,在 ​​google code​​​ 上面有简单的说明,第一版的发布博客也有简单的使用说明:​​中文分词 mmseg4j​​。为了更清楚说明在 solr 中使用 mmseg4j 中文分词,还是写篇博客吧。

目前有两个版本的 mmseg4j,1.7 版比较耗内存(一个词库目录就要 50M 左右),所以在默认jvm内存大小会抛出 OutOfMemoryErroy。我这里示例两个词库目录,所以不用目前最新版 1.7.2。而用 1.6.2 版。下载:​​mmseg4j-1.6.2​​​ 和 ​​词库​​​,或就下载一个​​源码包​​​(包括了词库,从源码构建请看:​​中文分词 mmseg4j 1.7.2 版发布​​),把 mmseg4j-all-1.6.2.jar 放到 solr.home/lib 。

mmseg4j 在 solr 中主要支持两个参数:mode、dicPath。mode 表示是什么模式分词(有效值:simplex、complex、max-word,如果输入了无效的默认用 max-word。)。dicPath 是词库目录可以是绝对目录,也可以是相对目录(是相对 solr.home 目录下的,dic 就会在 solr.home/dic 目录下找词库文件),如果不指定就是默认在 CWD/data 目录(程序运行当前目录的data子目录)下找。

改 solr 配置文件,主要是修改 schema.xml,我添加三个 field type,如下:

<fieldType name="textComplex" class="solr.TextField" positionIncrementGap="100" >
<analyzer>
<tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex" dicPath="dic"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="textMaxWord" class="solr.TextField" positionIncrementGap="100" >
<analyzer>
<tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="dic"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="textSimple" class="solr.TextField" positionIncrementGap="100" >
<analyzer>
<tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="simple" dicPath="n:/OpenSource/apache-solr-1.3.0/example/solr/my_dic"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
<fieldType name="textComplex" class="solr.TextField" positionIncrementGap="100" >   <analyzer>    <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="complex" dicPath="dic"/>     <filter class="solr.LowerCaseFilterFactory"/>   </analyzer> </fieldType> <fieldType name="textMaxWord" class="solr.TextField" positionIncrementGap="100" >  <analyzer>    <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="dic"/>    <filter class="solr.LowerCaseFilterFactory"/>   </analyzer> </fieldType> <fieldType name="textSimple" class="solr.TextField" positionIncrementGap="100" >   <analyzer>    <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="simple" dicPath="n:/OpenSource/apache-solr-1.3.0/example/solr/my_dic"/>    <filter class="solr.LowerCaseFilterFactory"/>   </analyzer> </fieldType>

说明:有多少不同的词库目录就会有多少个词库数组结构的实例,由上面的配置,会有两个实例。注意用 1.7.2 版会内存溢出。

定义几个字段:

<field name="simple" type="textSimple" indexed="true" stored="true"/>
<field name="complex" type="textComplex" indexed="true" stored="true"/>
<field name="text" type="textMaxWord" indexed="true" stored="true"/>
<field name="simple" type="textSimple" indexed="true" stored="true"/> <field name="complex" type="textComplex" indexed="true" stored="true"/> <field name="text" type="textMaxWord" indexed="true" stored="true"/>

再添加个 copyField(最后面加吧):

  1. <copyField source="text" dest="simple" />
  2. <copyField source="text" dest="complex" />
<copyField source="text" dest="simple" /> <copyField source="text" dest="complex" />

现在 mmseg4j 在 solr 中的使用配置好了。接下来安装 solr 到 tomcat。

solr 1.3 版早就出了,我就用它为示例的 solr。下载:​​solr-1.3.0​​​,如:解压放到 N:/OpenSource/apache-solr-1.3.0。在 tomcat 中怎么安装 solr 请看:​​Solr 使用入门介绍,以搜索论坛帖子为示例​​​, ​​ solr install​​​ ,​​ solr tomcat​​​,​​ solr on tomcat​​。

我是用 TOMCAT_HOME/conf/Catalina/localhost/solr.xml 的安装方式,指到 n:/OpenSource/apache-solr-1.3.0/example/solr。tomcat 6 可能没有这个目录,手动创建这目录。

启动 tomcat 可以看到 mmseg4j 的相关日志,然后在 ​​http://localhost:8080/solr/admin/analysis.jsp​​ 可以看 mmseg4j 的分词效果。在 Field 的下拉菜单选择 name,然后在应用输入 complex。分词的结果,如下图:

mmseg4j solr analysis 调试,点击放大

好了,可以运行起来了,那就添加个文档试下,在 n:/OpenSource/apache-solr-1.3.0/example/exampledocs 下创建 mmseg4j-solr-demo-doc.xml 文档:

<add>
<doc>
<field name="id">1</field>
<field name="text">京华时报2009年1月23日报道 昨天,受一股来自中西伯利亚的强冷空气影响,本市出现大风降温天气,白天最高气温只有零下7摄氏度,同时伴有6到7级的偏北风。</field>
</doc>
<doc>
<field name="id">2</field>
<field name="text">昨日金正日抵达长春市,进行两天的长春市内电话系统考察。</field>
</doc>
<doc>
<field name="id">3</field>
<field name="text">陈教授正在研究生命起源,他的研究生正在打球。</field>
</doc>
<doc>
<field name="id">4</field>
<field name="text">中国人民银行是中华人民共和国的中央银行。</field>
</doc>
</add>
<add>   <doc>     <field name="id">1</field>    <field name="text">京华时报2009年1月23日报道 昨天,受一股来自中西伯利亚的强冷空气影响,本市出现大风降温天气,白天最高气温只有零下7摄氏度,同时伴有6到7级的偏北风。</field>  </doc>  <doc>     <field name="id">2</field>    <field name="text">昨日金正日抵达长春市,进行两天的长春市内电话系统考察。</field>  </doc>  <doc>     <field name="id">3</field>    <field name="text">陈教授正在研究生命起源,他的研究生正在打球。</field>   </doc>  <doc>     <field name="id">4</field>    <field name="text">中国人民银行是中华人民共和国的中央银行。</field>   </doc> </add>

然后提交到 solr,在 cmd 下运行 post.jar,如下:

N:\OpenSource\apache-solr-1.3.0\example\exampledocs>java -Durl=http://localhost:8080/solr/update -Dcommit=yes -jar post.jar mmseg4j-solr-demo-doc.xml

SimplePostTool: version 1.2

SimplePostTool: WARNING: Make sure your XML documents are encoded in UTF-8, other encodings are not currently supported

SimplePostTool: POSTing files to http://localhost:8080/solr/update..

SimplePostTool: POSTing file mmseg4j-solr-demo-doc.xml

SimplePostTool: COMMITting Solr index changes..

注意:mmseg4j-solr-demo-doc.xml 要是 UTF-8 格式,不然提交后会乱码。

看下是否有数据:​​http://localhost:8080/solr/select/?q=*:*​​,有数据,应该正常。

然后,找“西伯利亚”.

simple:​​http://localhost:8080/solr/select?indent=on&q=simple:%E8%A5%BF%E4%BC%AF%E5%88%A9%E4%BA%9A&hl=on&hl.fl=simple%2Ccomplex%2Ctext&fl=id​​,结果如下:

<?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">0</int>
<lst name="params">
<str name="fl">id</str>
<str name="indent">on</str>
<str name="q">simple:西伯利亚</str>
<str name="hl.fl">simple,complex,text</str>
<str name="hl">on</str>
</lst>
</lst>
<result name="response" numFound="0" start="0"/>
<lst name="highlighting"/>
</response>
<?xml version="1.0" encoding="UTF-8"?> <response>  <lst name="responseHeader">  <int name="status">0</int>  <int name="QTime">0</int>  <lst name="params">   <str name="fl">id</str>   <str name="indent">on</str>   <str name="q">simple:西伯利亚</str>   <str name="hl.fl">simple,complex,text</str>   <str name="hl">on</str>  </lst> </lst> <result name="response" numFound="0" start="0"/> <lst name="highlighting"/> </response>

comlex:​​http://localhost:8080/solr/select?indent=on&q=complex:%E8%A5%BF%E4%BC%AF%E5%88%A9%E4%BA%9A&hl=on&hl.fl=simple%2Ccomplex%2Ctext&fl=id​​,结果如:

<?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">0</int>
<lst name="params">
<str name="fl">id</str>
<str name="indent">on</str>
<str name="q">complex:西伯利亚</str>
<str name="hl.fl">simple,complex,text</str>
<str name="hl">on</str>
</lst>
</lst>
<result name="response" numFound="1" start="0">
<doc>
<str name="id">1</str>
</doc>
</result>
<lst name="highlighting">
<lst name="1">
<arr name="complex">
<str>京华时报2009年1月23日报道 昨天,受一股来自中<em>西伯利亚</em>的强冷空气影响,本市出现大风降温天气,白天最高气温只有零下7摄氏度,同时伴有6到7级的偏北风。</str>
</arr>
</lst>
</lst>
</response>
<?xml version="1.0" encoding="UTF-8"?> <response>  <lst name="responseHeader">  <int name="status">0</int>  <int name="QTime">0</int>  <lst name="params">   <str name="fl">id</str>   <str name="indent">on</str>   <str name="q">complex:西伯利亚</str>   <str name="hl.fl">simple,complex,text</str>   <str name="hl">on</str>  </lst> </lst> <result name="response" numFound="1" start="0">  <doc>   <str name="id">1</str>  </doc> </result> <lst name="highlighting">  <lst name="1">   <arr name="complex">   <str>京华时报2009年1月23日报道 昨天,受一股来自中<em>西伯利亚</em>的强冷空气影响,本市出现大风降温天气,白天最高气温只有零下7摄氏度,同时伴有6到7级的偏北风。</str>   </arr>  </lst> </lst> </response>

text(其实是 max-word):​​http://localhost:8080/solr/select?indent=on&q=text:%E8%A5%BF%E4%BC%AF%E5%88%A9%E4%BA%9A&hl=on&hl.fl=simple%2Ccomplex%2Ctext&fl=id​​,结果:

<?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">15</int>
<lst name="params">
<str name="fl">id</str>
<str name="indent">on</str>
<str name="q">text:西伯利亚</str>
<str name="hl.fl">simple,complex,text</str>
<str name="hl">on</str>
</lst>
</lst>
<result name="response" numFound="1" start="0">
<doc>
<str name="id">1</str>
</doc>
</result>
<lst name="highlighting">
<lst name="1">
<arr name="text">
<str>京华时报2009年1月23日报道 昨天,受一股来自中<em>西</em><em>伯利亚</em>的强冷空气影响,本市出现大风降温天气,白天最高气温只有零下7摄氏度,同时伴有6到7级的偏北风。</str>
</arr>
</lst>
</lst>
</response>

下面是NGramTokenizerFactory分词设置

NGramTokenizerFactory
<fieldType name="text" class="solr.TextField"  positionIncrementGap="100">
<analyzer type="index" >
<tokenizer class="solr.NGramTokenizerFactory" minGramSize="2" maxGramSize="2"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query" >
<tokenizer class="solr.NGramTokenizerFactory" minGramSize="2" maxGramSize="2"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>