1 课程计划
1、什么是全文检索,如何实现全文检索
2、Lucence实现全文检索的流程
1)创建索引
2)查询索引
3、配置开发环境
4、入门程序
5、分析器的分析过程
1)测试分析器的分词效果
2)第三方中文分析器
6、索引库维护
1)添加文档
2)删除文档
3)修改文档
7、索引库查询
使用query子类查询
使用queryparser查询
2 什么是全文检索
什么是全文检索,搜索
数据的分类:可以分为在二类,
1)结构化数据
格式固定,长度固定,数据类型固定
例如数据库中的数据
2)非结构化数据
word文档,pdf文档、邮件、html
格式不固定,长度不固定,数据类型不固定
2、数据的查询
1)结构化数据的查询
SQL语句,查询结构化数据的方法,简单、速度快。
2)非结构化数据的查询。
从文本文件中,中找到包含spring单词的文件。
1、目测
2、使用程序文档读取到内存中,然后匹配字符串,顺序扫描
3、把结构化数据变成结构化数据。
先根据空格进行字符串拆分,得到一个单词列表,基于单词列表创建一个索引。
索引:一个为了提高查询速度,创建某种数据结构的集合。
3)全文检索
先创建索引,然后查询索引的过程叫做全文检索。
索引一次创建多次使用,表现为每次查询速度很快。
4)全文检索的应用场景
1、搜索引擎
2、站内搜索
电商搜索
只要是有搜索的地方就可以使用全文检索技术
三、什么是Lucene
Luncene是一个基于java开发的全文检索工具包
四、Luncene实现全文检索的流程
创建索引,查询索引
1、创建索引,
1)获得文档 原始文档:要基于那些数据来进行搜索,那么这些数据就是原始文档。
搜索引擎:使用爬虫
原始文件--》创建文档对晚---》分析文档---》根据空格
原始文档:要基于那些数据进行搜索,那么这些数据就是原始文档
搜索引擎:使用爬虫获得原始文档
站内搜索,数据库中的数据
案例,直接使用io流读取磁盘上的文件
2)构建文档对象
对应每个原始文档创建一个document对象
每个Document对象中包含 多个域
域中保存就是原始文档数据
域的名称
域 的值
每个文档都有一个唯一的编号,就是文档id
3)分析文档
就是分词的过程
根据空格进行字符串的拆分,得到一个单词的列表
把单词统一转换成小写
去掉标点符号
去除停用词,无意义的词
每个关键词都封装成一个term对象中
term中包含 两部分内容:关键词
关键词的所有的域
关键词本身
不同域 中拆行相同是不同的term
创建索引:基于关键字列表创建一个索引,保存到索引库中
索引库中关含,索引,docuemnt 对象,关键字和文档的对应关系
查询索引:
用户查询接口
用户输入查询条件的地方
例如:百度查询搜索框
把关键字,封装成一个查询对象
要查询的域
要搜索的关键字
执行查询:根据要查询的关锓词到对应的域上进行搜索
找到关键字,
4)渲染结果:
根据文档的id找到文档对象
对关键词进行高亮显示
分页处理
最终展示给用户看
入门程序:
需求:
实现一个文件的搜索功能,通过关键字,搜索文件,凡是文件名
1、创建索引
环境:下载luncen
http:luncen.apache.org
步骤:
1、创建一个索引库,指定索引保存的位置
2、基于directory对象创建一个indexwriter对象
3、读取磁盘上的文件,每个文件创建一个文档对象
4、
package com.wangjunji;
import jdk.internal.org.objectweb.asm.tree.analysis.Analyzer;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.store.FSDirectory;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Dictionary;
public class LuncenFirst {
public static void createIndex() throws IOException {
//创建 director对象,指定索引库保存位置
// new RAMDirectory()
//保存到磁盘上
FSDirectory directory = FSDirectory.open(new File("F:\\code\\Luncene\\index").toPath());
//基于dirctory对象,创建一个indexwriter对象
IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig());
//读取磁盘文件,对应每个文件创建一个文档对象
File dir = new File("F:\\code\\Luncene\\searchsource");
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".txt");
}
});
for (File file : files) {
String fileName = file.getName();
String filePath = file.getPath();
String fContext = FileUtils.readFileToString(file,"utf-8");
long fileSize = FileUtils.sizeOf(file);
//创建Filed
Field filldName = new TextField("name",fileName,Field.Store.YES);
Field filldPath = new TextField("path",filePath,Field.Store.YES);
Field filldContext = new TextField("content",fContext,Field.Store.YES);
Field filldSize = new TextField("size",fileSize+"",Field.Store.YES);
//创建文档对象
Document document = new Document();
document.add(filldName);
document.add(filldPath);
document.add(filldContext);
document.add(filldSize);
//对文件对象写入索引库
indexWriter.addDocument(document);
}
indexWriter.close();
}
//查询索引库
//步骤:创建一个dirctor对象。指定索引库的位置
//创建一个indexreader对象
//创建一个indexsearcher对象,构造方法中的参数indexReader对易用
//创建一个query对象,termquery
//执行查询,得到一个topdoc对象
//取查询得到一个topdocs对象
//取查询结果的总记录数
//取文档列表
//打印文档的内容
//关闭idnexread
public static void searchIndex() throws IOException {
FSDirectory directory = FSDirectory.open(new File("F:\\code\\Luncene\\index").toPath());
//基于dirctory对象,创建一个indexwriter
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//创建一个query对象
Query query = new TermQuery(new Term("content","spring"));
TopDocs topDocs = indexSearcher.search(query, 10);
System.out.println("查询总记录数"+topDocs.totalHits);
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
int docId = scoreDoc.doc;
Document doc = indexSearcher.doc(docId);
System.out.println(doc.get("name"));
System.out.println(doc.get("path"));
System.out.println(doc.get("content"));
System.out.println(doc.get("size"));
}
indexReader.close();
}
//查看分词器分词效果
public static void testTokenStream() throws Exception{
StandardAnalyzer analyzer = new StandardAnalyzer();
TokenStream tokenStream = analyzer.tokenStream("", "王马丁靴有东西暮云春霏霏封面");
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
tokenStream.reset();
while (tokenStream.incrementToken()){
System.out.println(charTermAttribute.toString());
}
tokenStream.close();
}
public static void main(String[] args) throws Exception {
//createIndex();
//searchIndex();
testTokenStream();
}
}
2)非结构化数据