Lucence学习笔记 2017-07-16
数据的分类
1. 结构化数据
概述:有固定类型或者有固定长度的数据,例如:数据库中的数据(mysql,oracle等), 元数据(就是windows中的数据)。
- 结构化数据的搜索方法:数据库中数据通过sql语句可以搜索;元数据(windows中的)通过windows提供的搜索栏进行搜索。
2. 非结构化数据
概述:没有固定类型和固定长度的数据,例如: world文档中的数据, 邮件中的数据
- 非结构化数据的搜索方法:Word文档使用ctrl+F来搜索
- 顺序扫描法:Ctrl+F中是使用的顺序扫描法,拿到搜索的关键字,去文档中,逐字匹配,直到找到和关键字一致的内容为止。
- 优点: 如果文档中存在要找的关键字就一定能找到想要的内容
- 缺点: 慢, 效率低
-
全文检索算法(倒排索引算法)
- 将文件中的内容提取出来, 将文字拆封成一个一个的词(分词), 将这些词组成索引(字典中的目录), 搜索的时候先搜索索引,通过索引找文档,这个过程就叫做全文检索
- 分词: 去掉停用词(a, an, the ,的, 地, 得, 啊, 嗯 ,呵呵),因为搜索的时候搜索这些词没有意义,将句子拆分成词,去掉标点符号和空格
- 优点: 搜索速度快
- 缺点: 因为创建的索引需要占用磁盘空间,所以这个算法会使用掉更多的磁盘空间,这是用空间换时间思
想的体现
- 顺序扫描法:Ctrl+F中是使用的顺序扫描法,拿到搜索的关键字,去文档中,逐字匹配,直到找到和关键字一致的内容为止。
-
原理
相当于字典,分为目录和正文两部分,查询的时候通过先查目录,然后通过目录上标注的页数去正文页查找需要的内容。
感悟:建立索引的过程,其实就是建立字典的目录的过程
Lucence
1.Lucence结构

-
索引(index)
-
文档(docudment)
感悟:Document对象其实就是对真实文件的一个抽取,抽取的过程中就是将文件的各种属性以域的概述进行了封装,比如一个文件包含很多属性:文件名,文件内容,文件大小,文件格式等,最终将多个 Field对象封装进了一个Document对象。(Document也可以封装数据库的一条记录,可以将需要进行索引的字段封装成document对象的 field)
索引:Document生成后,如果希望快速的进行检索,那么就需要对文档中的 field进行分词,分词后最小的单位是term(词元),哪些field要分词,哪些field不分词,是由field的类型决定的,比如StringField就是不进行分词的。
创建索引测试类示例代码
/**
* 创建索引测试类
* @author 77376
*
*/
public class IndexManageTest {
@Test
public void testIndexCreate() throws IOException{
//创建文档列表,保存多个document
List<Document> docList = new ArrayList<>();
//采集文档系统中的文档数据,放入Lucence
File dir = new File("F:\\KuGou\\searchsource");
//循环文件夹,取出文件
for(File file : dir.listFiles()){
//文件名
String fileName = file.getName();
//文件内容
String fileContent = FileUtils.readFileToString(file);
//文件大小
Long fileSize = FileUtils.sizeOf(file);
//文档对象,文件系统中的一个文件就是一个文档对象
Document doc = new Document();
//第一个参数:域名
//第二个参数:域值
//第三个参数:是否存储,是为yes,不存储为no
TextField nameField = new TextField("fileName", fileName, Store.YES);
TextField contentField = new TextField("fileContent", fileContent, Store.YES);
TextField sizeField = new TextField("fileSize", fileSize.toString(), Store.YES);
//将所有的域都存入文档中
doc.add(nameField);
doc.add(contentField);
doc.add(sizeField);
//将文档存入文档集合中
docList.add(doc);
}
//创建分词器,标准分词器,对英文分词效果好,对中文是单字分词
Analyzer analyzer = new StandardAnalyzer();
//指定索引和文档存储目录
Directory directory = FSDirectory.open(new File("F:\\KuGou\\dir"));
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
//创建索引和 文档写对象
IndexWriter indexWriter = new IndexWriter(directory, config);
//将文档加入到索引和文档的写对象中
for(Document doc : docList){
indexWriter.addDocument(doc);
}
//提交
indexWriter.commit();
//关闭
indexWriter.close();
}
}
基于Lucence的索引进行搜索示例代码
/**
* Lucence搜索示例代码
* @author 77376
*
*/
public class IndexSearchTest {
@Test
public void testIndexSearch() throws Exception{
//创建分词器(搜索时使用的分词器必须与创建索引时使用的分词器一致)
Analyzer analyzer = new StandardAnalyzer();
//创建查询对象
//第一个参数:默认搜索域
//第二个参数:分词器
//默认搜索域的作用:如何搜索语法中指定域名,就从指定域名中搜索,如果搜索时只写了查询关键字,则从默认搜索域中搜索
QueryParser queryParser = new QueryParser("fileContent", analyzer);
//查询语法: 域名:搜索的关键字
//Query query = queryParser.parse("fileName:apache");
Query query = queryParser.parse("java");
//指定索引和文档的目录
Directory directory = FSDirectory.open(new File("F:\\KuGou\\dir"));
//索引和文档的读取对象
IndexReader indexReader = IndexReader.open(directory);
//创建索引的搜索对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//第一个参数:指定查询语句对象
//第二个参数:指定显示多少条
TopDocs topDocs = indexSearcher.search(query, 5);
System.out.println("--------count--------" + topDocs.totalHits);
//从搜索结果对象中获取结果集
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
//获取docID
int docID = scoreDoc.doc;
//通过文档ID,从硬盘中取出对应的文档
Document document = indexReader.document(docID);
System.out.println("fileName : " + document.get("fileName"));
System.out.println("fileSize : " + document.get("fileSize"));
System.out.println("-------line-------");
}
}
}
查询方式(检索类型)
- TermQuery:
根据词进行搜索(只能从文本中进行搜索) - QueryParser:
根据域名进行搜索,可以设置默认搜索域,推荐使用. (只能从文本中进行搜索) - NumericRangeQuery:
从数值范围进行搜索 - BooleanQuery:
组合查询,可以设置组合条件,not and or.从多个域中进行查询
must相当于and关键字,是并且的意思
should,相当于or关键字或者的意思
must_not相当于not关键字, 非的意思
注意:单独使用must_not 或者 独自使用must_not没有任何意义 - MatchAllDocsQuery:
查询出所有文档 - MultiFieldQueryParser:
可以从多个域中进行查询,只有这些域中有关键词的存在就查询出来
网友评论