介绍
数据分类
我们生活中的数据总体分为两种:结构化数据和非结构化数据。
结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件
数据查询
- 结构化数据查询
常见的结构化数据也就是数据库中的数据。在数据库中搜索很容易实现,通常都是使用sql语句进行查询,而且能很快的得到查询结果。
为什么数据库搜索很容易?
因为数据库中的数据存储是有规律的,有行有列而且数据格式、数据长度都是固定的。 - 非结构化数据查询
1、使用顺序扫描,将文档读取到内存中再匹配字符串
2、将非结构化数据转为结构化数据
根据空格进行字符串拆分,得到一个单词列表,根据单词列表建立一个索引(索引,为了提高查询速度建立的一种数据结构的集合),然后根据单词和文档的对应关系找到文档列表,这个过程就是全文检索(先创建索引然后查询索引的过程叫做全文检索,一次创建可多次使用,表现为查询速度很快)。
应用场景
1、搜索引擎
2、站内搜索 论坛搜索、微博、文章搜索
3、电商搜素 淘宝、京东
什么是lucene
lucene是一个基于java的开源全文检索工具包
全文检索流程
用户查询接口(搜索框等)、关键字、执行查询、渲染结果
入门程序
配置环境
- 下载解压 https://lucene.apache.org/
- 创建工程
添加jar
lucene-analyzers-common-8.5.2.jar
lucene-core-8.5.2.jar
commons-io.jar
测试用例
创建一个目录作为索引库
创建一个java工程,并导入jar包。
创建一个director对象,指定索引库保存的位置(内存或磁盘)
基于director对象创建一个IndexWriter对象
读取磁盘上的文件,每个文件创建一个文档对象
创建field对象,将field添加到document对象中。
使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
关闭IndexWriter对象。
@Test
public void createIndex() throws IOException {
//创建一个director对象,指定索引库保存的位置(内存或磁盘)
Directory directory = FSDirectory.open(new File("D:\\Lucene\\index").toPath());
//基于director对象创建一个IndexWriter对象
IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig());
//读取磁盘上的文件,每个文件创建一个文档对象
File dir = new File("F:\\黑马最新\\00 讲义+笔记+资料\\5.流行框架\\61.Lucene\\lucene\\02.参考资料\\searchsource");
File[] files = dir.listFiles();
for (File file : files) {
String name = file.getName();
String path = file.getPath();
String content = FileUtils.readFileToString(file, "utf-8");
long size = FileUtils.sizeOf(file);
//创建field对象,将field添加到document对象中。
Document document = new Document();
//Field.Store.YES表示保存到磁盘,否则不保存
Field fieldName = new TextField("name",name,Field.Store.YES);
Field fieldPath = new TextField("path",path,Field.Store.YES);
Field fieldContent = new TextField("content",content,Field.Store.YES);
Field fieldSize = new TextField("size",size + "",Field.Store.YES);
document.add(fieldName);
document.add(fieldPath);
document.add(fieldContent);
document.add(fieldSize);
//使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
indexWriter.addDocument(document);
}
//关闭IndexWriter对象。
indexWriter.close();
}
查看索引库
可以使用luke查看索引中的内容
查询索引
第一步:创建一个Directory对象,也就是索引库存放的位置。
第二步:创建一个indexReader对象,需要指定Directory对象。
第三步:创建一个indexsearcher对象,需要指定IndexReader对象
第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。
第五步:执行查询。
第六步:返回查询结果。遍历查询结果并输出。
第七步:关闭IndexReader对象
@Test
public void selectIndex() throws IOException {
//创建一个Directory对象,也就是索引库存放的位置。
Directory directory = FSDirectory.open(new File("D:\\Lucene\\index").toPath());
//创建一个indexReader对象,需要指定Directory对象。
IndexReader indexReader = DirectoryReader.open(directory);
//创建一个indexsearcher对象,需要指定IndexReader对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//创建一个TermQuery对象,指定查询的域和查询的关键词。
TermQuery termQuery = new TermQuery(new Term("content", "spring"));
//执行查询。数字为只拿出10条数据
TopDocs topDocs = indexSearcher.search(termQuery, 10);
System.out.println("总记录数" + topDocs.totalHits);
//返回查询结果。遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
//获取文档id
int docId = scoreDoc.doc;
//通过id获取文档
Document document = indexSearcher.doc(docId);
System.out.println(document.get("name"));
System.out.println(document.get("path"));
System.out.println(document.get("size"));
}
//关闭IndexReader对象
indexReader.close();
}
分析器
标准分析器
在不指定分析器时默认会使用标准分析器(分析英文)
@Test
public void testTokenStream() throws IOException {
//创建一个分析器对象
Analyzer analyzer = new StandardAnalyzer();
//获得tokenStream
TokenStream tokenStream = analyzer.tokenStream("", "The Spring Framework provides a comprehensive programming and configuration model.");
//添加一个指针
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
//调用reset方法,不调用会抛出异常
tokenStream.reset();
//循环遍历
while (tokenStream.incrementToken()){
System.out.println(charTermAttribute.toString());
}
//关闭tokenStream
tokenStream.close();
}
处理中文的分析器IKAnalyzer(第三方的分析器)
- 测试
创建索引库
索引库的维护
-
各种Field
修改添加索引库的代码
-
删除全部
indexWriter.deleteAll();
-
针对删除(通过查询删除)
indexWriter.deleteDocuments(new Term("name", "apache"));
-
修改
-
查询
方案1:根据域和关键词查询(TermQuery),前面有
方案2:范围查询RangeQuery,(LongPoint 可以参与运算)
-
使用QueryParse进行查询(分词查询)
添加jar包lucene-queryparser-7.4.0.jar