• 如何在SOLR中嵌入自己的分词系统


    SOLR虽然为我们提供了分词的接入方法,但很显然并不奏效,搜遍了大江南北,也没有什么可参考的,大部分都是使用的IK或庖丁之类的分词~~,难 不成就这样永远活在别人的阴影中??答案是"NO!",如果是这样那就意味着屏蔽词管理,词典实时更新,实时持久化等多个个性化的产品需求得以在这些分词 系统上半路杀入,老鸟应该都明白这种做法的成本是太高了。

           SOLR推荐但失败的分词接入方法是在schema.xml字段配置文件中写入以下配置:

          

           编写自己的TokenFactory ,该类继成自 SOLR的BaseTokenizerFactory ,找到以下配置节点,并将 tokenizer的 class类 :替换掉。

        

    1. <tokenizer class="org.apache.lucene.analysis.cn.SolrTokenFactory"/>    
    2. <analyzer type="index">  
    3.   
    4.             <!-- <tokenizer class="org.apache.lucene.analysis.cn.SolrTokenFactory"/>   
    5. ->  
    6.   
    7. <tokenizer class="org.apache.lucene.analysis.cn.SolrTokenFactory"/>          
    8.        <!-- in this example, we will only use synonyms at query time  
    9.        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>  
    10.        -->  
    11.        <!-- Case insensitive stop word removal.  
    12.          add enablePositionIncrements=true in both the index and query  
    13.          analyzers to leave a 'gap' for more accurate phrase queries.  
    14.        -->  
    15.        <filter class="solr.StopFilterFactory"  
    16.                ignoreCase="true"  
    17.                words="stopwords.txt"  
    18.                enablePositionIncrements="true"  
    19.                />  
    20.        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>  
    21.        <filter class="solr.LowerCaseFilterFactory"/>  
    22.      </analyzer>  
    23.      <analyzer type="query">  
    24.        <tokenizer class="org.apache.lucene.analysis.cn.SolrTokenFactory"/>   
    25.           
    26. <!-- <tokenizer class="org.wltea.analyzer.solr.IKTokenizerFactory14"/> -->   
    27.              <filter class="solr.StopFilterFactory"  
    28.                ignoreCase="true"  
    29.                words="stopwords.txt"  
    30.                enablePositionIncrements="true"  
    31.                />  
    32.        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>  
    33.        <filter class="solr.LowerCaseFilterFactory"/>  
    34.      </analyzer>  

        把IK的源代码翻了个底朝天,也没看出自己的分词器和它的接入方法有什么区别,不是QUERY分词失败,就是写入的索引没有分词效果,一气之下就钻到SOLR的源代码里,经过一番苦战,终于苦尽甘来~,彻底搞定!

        废话少说,来解决方案:

        说明:因为修改了SOLR的部分代码,所以分词器在SCHEMA.xml的配置是彻底失效了,但是其他字段设定都沿用schema.xml.

       

        在这之前先说下SOLR加载schema.xml的步骤:

        调用栈:

       org.apache.solr.core.SolrCore 520行

        schema = new IndexSchema(config, IndexSchema.DEFAULT_SCHEMA_FILE, null);

        org.apache.solr.schema.IndexSchema 103行

          readSchema(lis);

      SOLR主要是通过 private void readSchema(InputStream is)  这个函数对分词解析器进行初始化,及对schema.xml中的各种类型进行实例化,同时写入到 :protected final HashMap<String, Analyzer> analyzers ,供外部系统调用。

       这次我们开到的函数就是 org.apache.solr.schema.IndexSchema  的 readSchema()函数。

         因为我们要将自己的分词解析器半路插进去,因此在这个函数的这个位置插入以下语句:

      

    1. try{  
    2.                 AbstractPluginLoader<FieldType> fieldLoader = new AbstractPluginLoader<FieldType>(  
    3.                         "[schema.xml] fieldType", true, true) {  
    4.   
    5.                     @Override  
    6.                     protected FieldType create(ResourceLoader loader, String name,  
    7.                             String className, Node node) throws Exception {  
    8.                         FieldType ft = (FieldType) loader.newInstance(className);  
    9.                         ft.setTypeName(name);  
    10.   
    11.                         String expression = "./analyzer[@type='query']";  
    12.                         Node anode = (Node) xpath.evaluate(expression, node,  
    13.                                 XPathConstants.NODE);  
    14.                         Analyzer queryAnalyzer = readAnalyzer(anode);  
    15.   
    16.                         // An analyzer without a type specified, or with  
    17.                         // type="index"  
    18.                         expression = "./analyzer[@type='index']";  
    19.                         anode = (Node) xpath.evaluate(expression, node,  
    20.                                 XPathConstants.NODE);  
    21.                         Analyzer analyzer = readAnalyzer(anode);  
    22.   
    23.                         if (queryAnalyzer == null)  
    24.                             queryAnalyzer = analyzer;  
    25.                         if (analyzer == null)  
    26.                             analyzer = queryAnalyzer;  
    27.                         if (analyzer != null) {  
    28.                             if(ft!=null && className.equals("solr.TextField")){  
    29.                                 ft.setAnalyzer(AnalyzerManager.getAnalyzer());  
    30.                                 ft.setQueryAnalyzer(AnalyzerManager.getAnalyzer());  
    31.                             }else{  
    32.                                 ft.setAnalyzer(analyzer);  
    33.                                 ft.setQueryAnalyzer(analyzer);  
    34.                             }  
    35.                                   
    36.                         }  
    37.                         return ft;  
    38.                     }  

    在 protected FieldType create(ResourceLoader loader, String name,
           String className, Node node) throws Exception { 

     这个函数体中,判断 className 的类名,因为我们需要对solr.TextField类型做重写,即改写text类型的分词器,所以需要加入以下判断:

      

    1. if (analyzer != null) {  
    2.                             if(ft!=null && className.equals("solr.TextField")){  
    3.                                 ft.setAnalyzer(AnalyzerManager.getAnalyzer());  
    4.                                 ft.setQueryAnalyzer(AnalyzerManager.getAnalyzer());  
    5.                             }else{  
    6.                                 ft.setAnalyzer(analyzer);  
    7.                                 ft.setQueryAnalyzer(analyzer);  
    8.                             }  
    9.                                   
    10.                         }  

    OK,重启SOLR,试试看,是不是奏效了??

  • 相关阅读:
    Bootstrap学习笔记(2)--栅格系统深入学习
    如何用手机访问电脑上的html文件
    Jquery学习笔记(11)--jquery的ajax删除用户,非常简单!
    Jquery学习笔记(10)--ajax删除用户,使用了js原生ajax
    Jquery学习笔记(9)--注册验证复习(未用到ajax)
    CSS学习笔记(3)--表格边框
    CSS学习笔记(2)--html中checkbox和radio
    Jquery学习笔记(8)--京东导航菜单(2)增加弹框
    Jquery学习笔记(7)--京东导航菜单
    CSS学习笔记(1)--浮动
  • 原文地址:https://www.cnblogs.com/wycg1984/p/1690244.html
Copyright © 2020-2023  润新知