中文检索(分词、同义词、权重)

来源:互联网 发布:mac自带预览抠图 编辑:程序博客网 时间:2024/05/16 14:21
1、首先导入Lucene相关包:
lucene-analyzers-common-4.7.1.jar
lucene-core-4.7.1.jar
lucene-facet-4.7.1.jar
lucene-highlighter-4.7.1.jar
lucene-queries-4.7.1.jar
lucene-queryparser-4.7.1.jar

2、然后把分词源码IK复制到项目的src文件夹下。IK是中文分词开源代码之一,lucene默认的分词器只能对英文分词,IK在此基础上做了些工作使得可以对中文分词。
如图:


3、在此基础上可以进行相应的开发:
(1)可以根据需要添加自己的扩展词典(分词词典),修改IKAnalyzer.xml文件即可。
(2)可以根据需要使用业务词典,业务词典的词带有权重,以特定的格式,如"="或空格。
(3)为同义词建立同义词索引,同义词最好写到一个同义词词典里,方便以后重建索引使用。
初步实现的源码可见:网盘/学习/代码实例/Lucene中文检索/LuceneTest
说明:
1、IK提供了中文分词,而Lucene默认的分词器不支持中文,所以在建立索引的时候要用到IK分词器
2、检索的时候可以使用IK提供的检索功能,也可以用Lucene提供的检索功能
     IK源码提供的多字段检索或单字段检索可以直接检索句子,因为它检索的时候会再一次调用分词器,把句子分词,然后对每个分词再检索。
     Lucene提供的检索只能对分词检索,也就是说如果你把一个句子当做参数去检索,lucene会把整个句子当做一个词,这肯定搜索不到答案。所以在检索之前要对句子做一次分词(要用IK提供的分词器)
     当不需要对每个分词的权重设置,也不需要用到同义词,而且多条件搜索不复杂,可以直接使用IK源码提供的搜索功能。如果希望加入同义词或对分词设置权重,不同字段的搜索之间的与或关系不同,这是就要用lucene提供的搜索功能。首先利用IK提供的分词功能把句子分词,再取得同义词,然后利用BooleanQuery来把各部分搜索合并起来:

Directory directory = FSDirectory.open(new File("D:\\lucene\\index"));
IndexReader ireader = ireader = DirectoryReader.open(directory);
IndexSearcher isearcher = new IndexSearcher(ireader); 

BooleanQuery booleanQuery=new BooleanQuery();

TermQuery query = null;

   for(String s:list){

      Term term1=new Term(字段1, s);

      query1=new TermQuery(term1);

      float weight1 = (float)2.0;

      query1.setBoost(weight1);

      Term term2=new Term(字段2, s);

      query2=new TermQuery(term2);

      float weight2 = (float)2.0;

      query2.setBoost(weight2);

      BooleanQuery bq=new BooleanQuery();

      bq.add(query1, BooleanClause.Occur.MUST);

      bq.add(query2, BooleanClause.Occur.MUST);

      booleanQuery.add(bq, BooleanClause.Occur.SHOULD);

     }

    TopDocs topDocs = isearcher.search(booleanQuery ,20);

其中list是句子的分词结果列表,字段1和字段2之间是与关系,也就是两字段都要含有关键字s,而每个关键字之间是或关系,即只要含有其中一个关键字就可以
如果只要搜索一个字段,则代码更简单:

for(String s:list){

      Term term=new Term(字段, s);

      query=new TermQuery(term);

      float weight = (float)2.0;

      query.setBoost(weight);

      booleanQuery.add(query , BooleanClause.Occur.SHOULD);

     }

可以根据需要修改它们之间的关系,通过设置MUSTSHOULD,如某两个字段是与关系,其它字段是或关系,某些分词是与关系,其它分词是或关系等等

分词过程:

      List<String> list = new ArrayList<String>();

      Analyzer analyzer = new IKAnalyzer();

      //获取LuceneTokenStream对象

       TokenStream ts = null;

      try {

         ts = analyzer.tokenStream(要分词的句子, new StringReader(要分词的句子));

          //获取词元文本属性

          CharTermAttribute term = ts.addAttribute(CharTermAttribute.class);

          //重置TokenStream(重置StringReader

         ts.reset();

         //迭代获取分词结果

         while (ts.incrementToken()) {

            list.add(term.toString());

         }

         //关闭TokenStream(关闭StringReader

         ts.end();

 

      } catch (IOException e) {

         e.printStackTrace();

      } finally {

         //释放TokenStream的所有资源

         if(ts != null){

            try {

            ts.close();

            } catch (IOException e) {

            e.printStackTrace();

            }

         }

       }

   












0 0