全文搜索引擎
传统的数据块查询 Like 查询效率很低
Lucene
- 定义 是apache旗下的顶级项目,是一个全文检索工具包。就是一个可以创建全文检索引擎系统的一堆jar包。可以使用他来构建全文检索系统,但是不能独立运行。
全文检索引擎系统:
放到tomcat下可以独立运行。对外提供全文检索服务。
-
顺序扫描算法
Ctrl + F 是使用顺序扫描算法,拿到搜索的关键字,去文档中,逐字匹配,指导和关键字一致的内容为止。 -
全文检索算法 (到拍索引算法)
将文件中的内容提取出来,将文字拆封成一个一个的词(分词),将这些词组成索引(字典中的目录),搜索的时候先搜索索引,通过索引找文档,这个过程就叫做全文检索。
优点: 搜索速度快
缺点: 以空间换区时间。 因为创建的索引需要占用磁盘空间,所以这个算法会使用掉更多的磁盘空间,这是用空间换时间。
原理相当于字典,查询的时候,先查询目录,然后通过目录标记的位置,去查找正文页的内容。 -
在全文索引工具中,都是由这样的三部分组成:
索引部分 (I am a boy)
分词部分
搜索部分 -
应用领域:
互联网全文检索引擎 (百度,谷歌,必应)
站内全文检索引擎(淘宝,京东 搜索功能)
优惠数据库查询(因为数据库中使用like关键字是全表扫描算法,查询慢) -
索引
域:词 这样的形式
它里面有指针执行这个词来源的文档。 -
文档:
Document对象,一个document中可以有多个field域对象,field对象中是key,value键值对的形式存在, 有域名和域值
一个document就是数据库表中的一条记录,一个Field域对象就是数据库表中的一行一列,这是一个通用的存储结构。
建立索引:
@Test
public void index() throws IOException {
// 1. 创建Directory
// Directory directory = new RAMDirectory(); //创建索引在内存中
Path indexPath = Paths.get("D:\\test\\index"); // 创建索引在硬盘中
Directory directory = FSDirectory.open(indexPath);
// 2. 创建IndexWriter
IndexWriterConfig iwf = new IndexWriterConfig(new StandardAnalyzer());
IndexWriter writer = null;
try {
writer = new IndexWriter(directory, iwf);
// 3. 创建Document对象
Document doc = null;
File f = new File("D:\\test\\lucene");
for (File file : f.listFiles()) {
// 4.为document添加Field
doc = new Document();
doc.add(new TextField("content", new FileReader(file)));
doc.add(new StringField("name", file.getName(), Store.YES));
doc.add(new StringField("path", file.getAbsolutePath(), Store.YES));
// 5.通过IndexWriter添加到文档到索引中
writer.addDocument(doc);
System.out.println("为 " + file.getName() + " 添加索引完毕!");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
writer.close();
directory.close();
}
}
查询
/**
* 搜索
* @throws IOException
* @throws ParseException
*/
@Test
public void search() throws IOException, ParseException{
//1 创建Directory
Path indexPath=Paths.get("D:\\test\\index");
Directory dir=FSDirectory.open(indexPath);
//输入流,reader
//2 创建IndexReader
IndexReader reader=DirectoryReader.open(dir);
//3 根据IndexReader 创建IndexSearcher
IndexSearcher searcher=new IndexSearcher(reader);
// 4.创建搜索的Query
QueryParser parser = new QueryParser("content", new StandardAnalyzer());
Query query = parser.parse("java"); //查询保护北京的文档
//5.根据search搜索并且返回TopDocs
TopDocs tds = searcher.search(query, 10); //查询10条
//6. 根据TopDocs获取ScoreDos对象
ScoreDoc [] docs = tds.scoreDocs;
for(ScoreDoc sd : docs){
//7.根据seracher和scoreDoc对象获取具体的Document对象
//8.根据Doucment对象获取需要的之
Document d = searcher.doc(sd.doc);
String content = d.get("content");
String path = d.get("path");
String name = d.get("name");
System.out.println("name= "+ name + " path "+ path +" content "+ content);
}
reader.close();
}
域的详细介绍
-
是否分词
分词的作用是为了索引
需要分词: 文件名称,文件内容
不需要分词: 不需要索引的域不需要分词,还有就是分词后毫无意义的域不需要分词
比如Id,身份证号 -
是否索引
索引的目的是为了搜索
需要搜索的域一定要创建索引,只有创建了索引才能被搜索出来。
不需要搜索的域可以不创建索引
需要索引:文件名称、文件内容
是否存储: 看个人需要,将内容放入document文档中保存出来,会额外占用磁盘空间。
如果需要搜索的时候,需要马上显示出来,可以放到document中,也就是需要存储,这样查询显示速度快。 -
域的各种类型
StringField 字符串
LongField long型
StoredField 图片地址
TextField 文本域