Java技术文章@IT·互联网程序员

Lucene--相关度排序和中文分析器

2017-05-19  本文已影响471人  我可能是个假开发

一、相关度排序

1.什么是相关度排序

相关度排序是查询结果按照与查询关键字的相关性进行排序,越相关的越靠前。比如搜索“Lucene”关键字,与该关键字最相关的文章应该排在前边。

2.相关度打分

Lucene对查询关键字和索引文档的相关度进行打分,得分高的就排在前边。如何打分呢?Lucene是在用户进行检索时实时根据搜索的关键字计算出来的,分两步:

  1. 计算出词(Term)的权重
  2. 根据词的权重值,计算文档相关度得分。

什么是词的权重?
明确索引的最小单位是一个Term(索引词典中的一个词),搜索也是要从Term中搜索,再根据Term找到文档,Term对文档的重要性称为权重,影响Term权重有两个因素:

3.设置boost值影响相关度排序

boost是一个加权值(默认加权值为1.0f),它可以影响权重的计算。

设置boost是给域(field)或者Document设置的。

3.1 在创建索引时设置

如果希望某些文档更重要,当此文档中包含所要查询的词则应该得分较高,这样相关度排序可以排在前边,可以在创建索引时设定文档中某些域(Field)的boost值来实现,如果不进行设定,则Field Boost默认为1.0f。一旦设定,除非删除此文档,否则无法改变。

@Test
public void setBoost4createIndex() throws Exception {
    // 创建分词器
    Analyzer analyzer = new StandardAnalyzer();

    IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
            analyzer);
    Directory directory = FSDirectory.open(new File("E:\\11-index\\0728"));
    // 创建IndexWriter对象,通过它把分好的词写到索引库中
    IndexWriter writer = new IndexWriter(directory, cfg);

    Document doc = new Document();
    Field id = new StringField("id", "11", Store.YES);
    Field description = new TextField("description", "测试设置BOOST值 lucene",
            Store.YES);
    // 设置boost
    description.setBoost(10.0f);
    // 把域添加到文档中
    doc.add(id);
    doc.add(description);
    writer.addDocument(doc);
    // 关闭IndexWriter
    writer.close();
}

输出:

输出.png

3.2 在查询索引时设置

在MultiFieldQueryParser创建时设置boost值。

@Test
public void multiFieldQueryParser() throws Exception {
    // 创建7.3.2 MultiFieldQueryParser
    // 默认搜索的多个域的域名
    String[] fields = { "name", "description" };
    Analyzer analyzer = new StandardAnalyzer();
    Map<String, Float> boosts = new HashMap<String, Float>();
    boosts.put("name", 200f);
    MultiFieldQueryParser parser = new MultiFieldQueryParser(fields,
            analyzer, boosts);

    // Query query = parser.parse("name:lucene OR description:lucene");
    //等同于name:lucene OR description:lucene
    Query query = parser.parse("java");
    System.out.println(query);
    doSearch(query);
}

二、中文分词器

1.什么是中文分词器

英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开。而中文则以字为单位,字又组成词,字和词再组成句子。所以对于英文,我们可以简单以空格判断某个字符串是否为一个单词,比如I love China,love 和 China很容易被程序区分开来;但中文“我爱中国”就不一样了,电脑不知道“中国”是一个词语还是“爱中”是一个词语。把中文的句子切分成有意义的词,就是中文分词,也称切词。我爱中国,分词的结果是:我 爱 中国。

2.Lucene自带的中文分词器

上边两个分词器无法满足需求。

3.第三方中文分词器

4.使用中文分词器IKAnalyzer

Ikanalyzer.png

IKAnalyzer继承Lucene的Analyzer抽象类,使用IKAnalyzer和Lucene自带的分析器方法一样,将Analyzer测试代码改为IKAnalyzer测试中文分词效果。

如果使用中文分词器ik-analyzer,就在索引和搜索程序中使用一致的分词器ik-analyzer。

4.1添加jar包

jar包.png

4.2 修改分词器代码

// 创建分词器,标准分词器
// Analyzer analyzer = new StandardAnalyzer();
// 使用ikanalyzer
Analyzer analyzer = new IKAnalyzer();

5.扩展中文词库

将以下文件拷贝到config目录下

所需的文件.png

从ikanalyzer包中拷贝配置文件到classpath下。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
<properties>  

    <comment>IK Analyzer 扩展配置</comment>
    <!-- 用户可以在这里配置自己的扩展字典 -->
     <entry key="ext_dict">dicdata/mydict.dic</entry> 
     <!-- 用户可以在这里配置自己的扩展停用词字典    -->
    <entry key="ext_stopwords">dicdata/ext_stopword.dic</entry> 

</properties>

如果想配置扩展词和停用词,就创建扩展词的文件和停用词的文件,文件的编码要是utf-8。

注意:不要用记事本保存扩展词文件和停用词文件,那样的话,格式中是含有bom的。

添加扩展词文件:ext.dic,内容:我爱中国

6.使用luke测试中文分词

第一步:将ikanalyzer的jar包,拷贝到luke工具的目录

测试1.png

使用Luke测试第三方分词器分词效果,需通过java.ext.dirs加载jar包:
可简单的将第三方分词器和lukeall放在一块儿,cmd下运行:

11.png

第二步:使用命令打开luke工具:

java -Djava.ext.dirs=. -jar lukeall-4.10.3.jar
测试2.png
上一篇下一篇

猜你喜欢

热点阅读