lucene实例与源码解析

2020-08-04 21:28:59 浏览数 (1)

lucene是什么?

全文检索的引擎工具包,实现了全文检索的类库。 全文检索,将查询的目标对象提取出来构造一套索引,查询索引得到数据结果。

lucene有什么用?怎么用?

lucene的使用非常简单,构建索引,查询 主要作用是电商平台的搜索。

  1. 构造索引:(文件系统/数据库/网上数据/)->初始化lucene可以实现的对象->分析文档对象(分词,分析)->创建索引。
  2. 搜索索引获取目标文档:用户通过界面输入查询对象->创建查询索引->去搜索库查询->渲染结果
lucene开发搭建

开发思路:

  1. 构建索引

将原始数据放入到lucene的document对象, 并设置好对象。

将document进行分析(分词)

域的三个属性,分词,索引,存储

代码语言:javascript复制
 document.add(new TextField(FIELD,"hello world", Field.Store.YES));
 document.add(new StoredField(FIELD,"hello china"));

TextField 模型进行分词,Field.Store.YES 表示进行存储(即可以提供返回结果) Field.Store.NO 表示不进行存储 (表示进行分词作为索引,但不存储提供返回结果) new StoredField(FIELD,"hello china") 指的是只提供存储

2.将document进行分词,得到索引

analyzer 分词器,中文分词器

创建索引目录,创建构造索引的配置对象

indexWriter构造索引

3.创建查询对象

4.执行搜索,指定索引目录

实例代码

本实例代码使用的是lucene8.0.0,jdk 8 使用maven配置的项目,maven配置见下

代码语言:javascript复制
public class LuceneIndex {

    //创建索引存储位置
    private static final String INDEX_LOCATION = "/opt/project-get/luceneDemo/lucene";
    //设置lucene域名
    private static final String FIELD = "content";


    public static void index() throws IOException {
        //这里注意lucene8.0.0    FSDirectory.open() 内的参数是path类型

        // 打开lucene的存储目录
        Directory dirLucene = FSDirectory.open(Paths.get(INDEX_LOCATION));

        // 构建索引
        //注意这里一定要进行配置分词器,默认的分词器是按照英文设置的,这里采用的版本号默认是8.0.0
        IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());
        IndexWriter indexWriter = new IndexWriter(dirLucene,config);


        //创建文档
        Document document = new Document();
        //向文档中添加域
        document.add(new TextField(FIELD,"hello world", Field.Store.YES));

        Document document1 = new Document();
        document1.add(new StoredField(FIELD,"hello china"));

        Document document2 = new Document();
        document2.add(new TextField(FIELD," I love you", Field.Store.YES));

        Document document3 = new Document();
        document3.add(new TextField(FIELD,"hello zhao ", Field.Store.NO));

        //将文档添加到本地索引中
        indexWriter.addDocument(document);
        indexWriter.addDocument(document1);
        indexWriter.addDocument(document2);
        indexWriter.addDocument(document3);

        indexWriter.commit();
        indexWriter.close();
    }

    public static  void search(String item) throws IOException{
        //获取lucene本地存储路径
        Directory dir = FSDirectory.open(Paths.get(INDEX_LOCATION));
        //获取索引读取器
        IndexReader indexReader = DirectoryReader.open(dir);
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        //读取查询关键词
        TermQuery query = new TermQuery(new Term(FIELD,item));
        //获取前10返回结果
        TopDocs topN = indexSearcher.search(query,10);

        for(int i=0;i < topN.totalHits.value; i  ){
            Document doc = indexSearcher.doc(topN.scoreDocs[i].doc);

            System.out.println("doc" i ":"" doc.get(FIELD) """);
            System.out.println("score: "   topN.scoreDocs[i].score   """);
        }
    }

    public static void main(String[] args) throws IOException {
        //索引只用创建一次
        index();
        
        search("world");
    }

}

结果:

代码语言:javascript复制
doc0:"hello world"
score: 0.49705765"

最后的分数是,lucene使用布尔和VSM两个模型的结合,来进行搜索关键词与文档的打分操作,判断文档与关键词的相似性和相关性。

代码语言:javascript复制
 <dependencies>
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-core</artifactId>
        <version>8.0.0</version>
    </dependency>

    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-highlighter</artifactId>
        <version>8.0.0</version>
    </dependency>

    <!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-common -->
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-analyzers-common</artifactId>
        <version>8.0.0</version>
    </dependency>

    <!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-memory -->
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-memory</artifactId>
        <version>8.0.0</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>

    <!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-queryparser -->
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-queryparser</artifactId>
        <version>8.0.0</version>
    </dependency>

分析程序

目前搜索引擎采取的处理大量查询数据的思路都是,事先把跟关键词相匹配数据存储起来,查找的时候直接把存储好的数据进行返回。

在我们指定的索引存储位置处生成了几个文件:

代码语言:javascript复制
_0.cfe      索引信息的合成文件,仅仅作为减少索引读取时文件句柄的数量,提高性
能之用。
_0.cfs      索引信息的合成文件,仅仅作为减少索引读取时文件句柄的数量,提高性
能之用。
_0.si       段(Segment)文件,存储着一个段的元信息
segments_1  全局性文件,保存着索引的提交点(commit point)信息。在一个完整的索引结构中两个文件各有一个
write.lock  生成索引时保护索引结构的文件,

进行存储的就是内容分词后的词和对应的文档关系。

在lucene中的索引,被称作“反向索引”或者是“倒排索引”,称作反向主要是因为,在关系型数据库中我们一般将id作为索引,内容作为查询存储结果,在lucene中则是将内容分词后的结果作为索引,将id作为索引的结果进行返回。

然后再通过id进行查询,返回内容信息。

lucene的检索模型

lucene使用两个模型的结合,来进行搜索关键词与文档的打分操作。

  1. 布尔模型
布尔模型,搜索过程就是判断文档与用户意图是否相关的一个过程,是逻辑运算(也称布尔运算)的过程

对于一个用户输入的关键词,搜索引擎要布尔运算判断每篇文献是否含有这个关键词,如果含有关键词,则给这篇文章一个逻辑值——真(TRUE 或 1),否则,给它一个逻辑值——假(FALSE 或 0)。

2.VSM模型

是一种代数模型。该模型主要用于解决文本相似度的问题,搜索关键词与对应网页相似度可以视为文本相似度的问题。

模型基于这样一种假设:文档中词与词是相互独立,豪无关联的个体(又称”词袋模型”)

对于一个词汇量为 N 的文档集 ,其中每一篇文档都是一个 N 维的向量;词汇表中的每一个词的 ID 对应着向量中 的一个位置,词的权重为向量位置上的值。如果文档中没有该词,那么该位置上的值为 0 。

VSM 模型用 TF-IDF 来度量词的权重。 TF(Term Frequency):文档中的词频。 DF(Document Frequency):文档集中含该词的文档份数。 IDF(Inverse Document Frequency) = log10(N/DF) ; N 表示文档集中文档的总数。

Lucene 的数据模型

整个lucene文件的数据文件结构有:

Lucene 中可搜索的实体都表现为文档(document),它由字段(field)和值(value)组成。每个字段值都由一个或多个可搜索的元素——词汇(term)。一个或者多个文档(document)构成索引中的段(segment);一个或者多个段(Segment)构成一个完整的索引数据集。

0 人点赞