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)非结构化数据