lucene是什么?
全文检索的引擎工具包,实现了全文检索的类库。 全文检索,将查询的目标对象提取出来构造一套索引,查询索引得到数据结果。
lucene有什么用?怎么用?
lucene的使用非常简单,构建索引,查询 主要作用是电商平台的搜索。
- 构造索引:(文件系统/数据库/网上数据/)->初始化lucene可以实现的对象->分析文档对象(分词,分析)->创建索引。
- 搜索索引获取目标文档:用户通过界面输入查询对象->创建查询索引->去搜索库查询->渲染结果
lucene开发搭建
开发思路:
- 构建索引
将原始数据放入到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使用两个模型的结合,来进行搜索关键词与文档的打分操作。
- 布尔模型
布尔模型,搜索过程就是判断文档与用户意图是否相关的一个过程,是逻辑运算(也称布尔运算)的过程
对于一个用户输入的关键词,搜索引擎要布尔运算判断每篇文献是否含有这个关键词,如果含有关键词,则给这篇文章一个逻辑值——真(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文件的数据文件结构有: