首页
学习
活动
专区
工具
TVP
发布

Lucene基本概念及使用

1. 搜索引擎组件

1.1

索引组件

为了快速搜索大量的文本,必须针对文本建立索引,将文本内容转换成能够进行快速搜索的格式。

这个过程就叫做索引操作(indexing),输出就是索引(index)

1.1.2 建立文档

获取原始内容之后,就需要对内容进行索引,首先必须将内容转换成文档,以供搜索引擎使用。

文档主要包括几个带值的域,比如标题、正文、摘要、作者和链接(URL)。

然后需要将原始内容中的文本提取出来写入各个文档。

1.1.3 文档分析

搜索引擎不能直接对文本进行索引,而必须将文本分割成一系列被称为 词汇单元 的独立原子元素。

这一步骤决定文档中的文本域如何分割成 词汇单元 系列。

Lucene 提供了大量内嵌的分析器能够轻松完成这步操作

1.1.4 文档索引

在本步骤中,文档将被加入到索引列表。

1.2

搜索组件

搜索处理过程就是从索引中查找单词,从而找到包含该单词的文档。

1.2.1 建立查询

搜索请求会被转换成搜索引擎使用的 查询(query) 对象格式。

查询对象可能很简单,也可能很复杂。 Lucene 提供了一个称之为 查询解析器(QueryParser) 的强大开发包,用它可以根据通用查询语法将用户输入的文本处理成查询对象。

查询语句可以包含 布尔运算、短语查询或通配符查询。

1.2.2 搜索查询

查询检索索引并返回与查询语句匹配的文档,结果返回时按照查询请求来排序

常见的搜索理论模型:

1.纯布尔模型:文档不管是否匹配查询请求,都不会被评分,匹配文档与评分不相关,一条查询仅获取所有匹配文档集合的一个子集。

2.向量空间模型:查询语句和文档都是高维空间的向量模型,这里每一个独立的项都是一个维度,查询语句和文档之间的相关性或相似性由各个向量之间的距离计算得到。

3.概率模型:采用全概率的方法来计算文档和查询语句匹配的概率。

Lucene 采用了 空间向量模型和纯布尔模型

2. 核心技术

Lucene 是一个全文搜索框架

● 倒排索引

● 压缩算法

● 二元搜索

2.1

倒排索引

● 根据属性的值来查找记录,这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性,而是由属性值来确定记录的位置,因而成为倒排索引。

● 单词——文档矩阵

3. Lucene

的工作方法

Lucene 提供的服务实际包含两部分,一入一出:

入就是写入,将提供的源(本质上是字符串)写入索引或者将其从索引中删除;

出就是读取,向用户提供全文搜索服务,让用户可以通过关键词定位源。

● 写入:源字符首先经过 analyzer 处理,包括:分词,拆分成一个个单词;去除 stopword 。将源中需要的信息加入 Document 的各个 Field 中,并把需要索引的 Field 索引起来,把需要存储的 Field 存储起来。

● 读取:用户提供关键词,经过 analyzer 处理,对处理后的关键词搜索索引,找出对应的 Document。用户根据需要从找到的 Document 中提取出需要的 Field。

document:用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。一条记录经过索引之后,就是以一个 Document 的形式存储在索引文件中的。用户进行搜索,也是以 Document 列表的形式返回。

field:一个 Document 可以包含多个信息域,例如一篇文章可以包括标题、正文、最后修改时间等信息域,这些信息域是通过 Field 在 Document 中存储的。

Field 有两个属性可选:存储和索引。通过存储属性,可以控制是否对这个 Field 进行索引。

——张嘉佳《从你的全世界路过》

4. 示例代码

4.1

4.1 导入依赖

org.apache.lucene

lucene-core

5.5.4

org.apache.lucene

lucene-queries

5.5.4

org.apache.lucene

lucene-queryparser

5.5.4

org.apache.lucene

lucene-analyzers-common

5.5.4

org.apache.lucene

lucene-highlighter

5.5.4

commons-io

commons-io

2.5

commons-lang

commons-lang

2.5

commons-logging

commons-logging

1.2

4.2

环境准备

准备 index 和 data 两个目录,分别用于存放索引和文档

● data 随便从其他项目中复制了几个 LICENSE

● index 保持为空,当 Lucene 运行的时候会自动进行创建

4.3

创建索引

public classCreateIndex{

/*

* 索引目录

*/

public static finalString INDEX_DIR ="/Users/destiny/IdeaProjects/lucene-demo/src/main/resources/index";

/*

* 文本目录

*/

public static finalString DATA_DIR ="/Users/destiny/IdeaProjects/lucene-demo/src/main/resources/data";

public voidcreateIndex() throwsIOException {

// 目录对象,描述了索引的存放位置,需要由 Path 进行初始化

Directory directory = FSDirectory.open(Paths.get(INDEX_DIR));

// 创建分词器

Analyzer analyzer =newStandardAnalyzer();// 由分词器对 IndexWriterConfig 进行初始化

IndexWriterConfig indexWriterConfig =newIndexWriterConfig(analyzer);

indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

IndexWriter indexWriter =newIndexWriter(directory, indexWriterConfig);

File file =newFile(DATA_DIR);

File[ ] files = file.listFiles();

if(files !=null) {

// 读取并遍历文本路径下的所有文件,用于生成文档及其索引

for(File f : files) {

// 创建文档

Document document =newDocument();// 为文档设置 Field

document.add(newStringField("filename", f.getName(), Field.Store.YES));

document.add(newTextField("content", FileUtils.readFileToString(f, Charset.defaultCharset()), Field.Store.YES));

document.add(newLongField("lastModify", f.lastModified(), Field.Store.YES));

// 写入索引

indexWriter.addDocument(document);

}

}

indexWriter.close();

}

public static voidmain(String[ ] args)throwsIOException {

CreateIndex createIndex =newCreateIndex();

createIndex.createIndex();

}

}

运行完毕之后,发现 index 路径下多了一些文件,即为文档的索引。

4.4

查询索引

public classSearchIndex{

public voidsearch() throwsIOException, ParseException {

// 打开索引所在路径

Directory directory = FSDirectory.open(Paths.get(CreateIndex.INDEX_DIR));

IndexReader indexReader = DirectoryReader.open(directory);

IndexSearcher indexSearcher =newIndexSearcher(indexReader);

QueryParser queryParser =newQueryParser("content", new StandardAnalyzer());

Query query = queryParser.parse("from");

// 找到符合条件的前 10 条 Document 的索引的集合

TopDocs search = indexSearcher.search(query,10);

// 遍历集合并打印文件名称

for(ScoreDoc scoreDoc : search.scoreDocs) {

public static voidmain(String[] args)throwsIOException, ParseException {

SearchIndex searchIndex =newSearchIndex();

searchIndex.search();

}

}

查询结果:

5. 理解索引

过程核心类

执行简单的索引过程需要用到以下几个类:

● IndexWriter

● Directory

● Analyzer

● Document

● Field

5.1

IndexWriter

IndexWriter(写索引)是索引过程的核心组件,这个类负责创建新索引或者打开已有索引,以及向索引中添加、删除或者是更新被索引文档的信息。为开发者提供针对索引文件的写入操作,但不能用于读取或者搜索索引。IndexWriter 需要开辟一定的空间用来存储索引,该功能可以由 Directory 完成。

5.2

Directory

Directory 描述了 Lucene 索引存放的位置。它是一个抽象类,其实现类负责具体指定索引的存储路径。在上面的例子中,我们使用 FSDirectory.open() 方法来获取真实文件在文件系统中的存储路径,然后将她们依次传递给 IndexWriter 类的构造方法。

IndexWriter 不能直接索引文本,需要先由 Analyzer 将文本分割成独立的单词才行。

5.3

Analyzer

文本文件在被索引之前,需要经过 Analyzer 处理,Analyzer 由 IndexWriter 的构造方法来指定,负责从被索引文本文件中提取词汇单元,并剔除剩下的无用信息。如果被索引的内容不是纯文本文件,那就需要先将其转换成文本文档。

Analyzer 是一个抽象类,其实现类中:

● 有的用于跳过停用词(指一些常用且不能帮 助区分文档的词,如a、an、the、in 和 on 等)

● 有的用于把词汇转换成小写,以使得搜索过程不区分大小写

● 等等

分析器的分析对象为文档。

5.4

Document

Document 代表一些 域(Field) 的集合,可以将 Document 理解为虚拟文档,如 Web页面、邮件信息等。文档的域代表文档或者文档相关的一些元数据。

Lucene 只处理文本和数字,Lucene 的内核本身只处理 java.lang.String 和 java.io.Reader 对象和本地数字类型

Document 对象的结构比较简单,为一个多个 Field 对象的容器, Field 是指包含能被索引的文本内容的类。

5.5

Field

索引中,每个文档都包含一个或者多个不同命名的域,这些域包含在 Field 类中。

每个域都有一个域名和对应的值,以及一组选项来精确控制 Lucene 索引操作各个域值。

6. 理解搜索

过程核心类

核心类:

● IndexSearcher

● Term

● Query

● TermQuery

● TocDocs

6.1

IndexSearcher

用于搜索 IndexWriter 所创建的索引,可以将它看做一个以只读方式打开索引的类。

它需要利用 Directory 实例来掌握前期创建的索引,然后才能提供大量的搜索方法,最简单的搜索方法是将单个 Query 对象和 int topN 所谓该方法的参数,返回一个 TopDocs 对象。

6.2

Term

Term 是搜索功能的基本单元,与 Field 对象类似,Term 对象包含一对字符串元素:域名和单词,注意 Term 对象还与索引操作有关。

6.3

Query

Lucene 含有许多具体的 Query 子类

6.4

TermQuery

是 Lucene 提供的最基本的查询类型,也是简单的查询类型之一,它用来匹配指定域中包含特定值的文档。

6.5

TopDocs

TopDocs 类是一个简单的容器指针,指针一般指向前 N 个排名的搜索结果,搜索结果即匹配查询条件的文档。TopDocs 会记录前 N 个结果中每个结果的 int docID 和浮点型分数。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180510G24RKY00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券