1 全文检索 和 索引

1.1 索引

将非结构化数据中的一部分信息 取出来,重新组织,使其变得有一定结构,然后对此有 一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中 取出的然 后重新组织的信息,我们称之索引。

例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结 构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫 。然而字的某 些信息可以 取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种 可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。 我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据—— 也即对字的解释。

1.2 全文检索

这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。

2 Lucene实现全文检索的流程

2.1 索引和搜索流程图

2.2 创建索引

将用户需要搜索的文档内容进行索引,索引存储在索引库中。索引库位于本地磁盘中。

2.2.1 获得原始文档

可以使用网络爬虫采集一定量的文本数据,比如新闻信息。采集后将数据从数据库中转移到本地磁盘中。

2.2.2 创建文档对象

获取原始内容的目的是为了索引,在索引前需要将原始内容创建成文档(Document),文档包括多个域Field和域中存储的内容。
我们可以将磁盘中的一个文件当成一个document,document中包含field和对应的value。

2.2.3 分析文档

分析的过程是经过对原始文档的提取单词、字母大小写转换、去除标点符号、去除停用词等过程成圣最终的与会单词。比如下面的文档的分析过程如下:

原文:Hello,welcome to the java world!
分析结果:Hello、welcome、java、world

每一个单词是一个term,不同的域中拆分出来的相同单词是不同的term。term中包含field和value。
分析过程中会涉及到分析器,用来根据语义进行分词,中文的较为复杂。

2.2.4 创建索引

对所有文档分析得到的单词进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的单词而找到Document。
传统的搜索方式是顺序扫描法,在Lucene中所使用的索引方法是倒排索引法。即根据索引值去查找文档,而不是去遍历文档来扫描关键字。

3 程序实现

3.1 准备工作

  • 创建原始文档:在本地磁盘中创建一个目录,将原始文本存储于其中。
  • 创建索引库:在本地磁盘中创建一个空目录,用于存储索引。

3.2 引入相关jar包(POM)

 <dependencies><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>4.10.3</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-queryparser --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><version>4.10.3</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-common --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>4.10.3</version></dependency><!-- https://mvnrepository.com/artifact/commons-io/commons-io --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency><!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>

3.3 了解相关Field

3.4 测试代码

public class LuceneTest
{/*** 创建索引** @Author NikoBelic* @Date 07/03/2017 19:01*/@Testpublic void testIndexCreate() throws IOException{// 指定文档和索引的存储目录Directory indexDir = FSDirectory.open(new File("/Users/lixiwei-mac/Documents/DataSet/lucene/index"));// 标准分词器(英文效果好,中文单字分词)Analyzer analyzer = new IKAnalyzer();IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);IndexWriter indexWriter = new IndexWriter(indexDir, config);// 采集文档中的数据放入Lucene中File sourceDir = new File("/Users/lixiwei-mac/Documents/DataSet/lucene/searchsource");for (File f : sourceDir.listFiles()){String fileName = f.getName();String fileContent = FileUtils.readFileToString(f);String filePath = f.getPath();long fileSize = FileUtils.sizeOf(f);// (field_name,field_value,need_stored?)Field fileNameField = new TextField("filename", fileName, Field.Store.YES);Field fileContentField = new TextField("content", fileContent, Field.Store.NO);Field filepPthField = new StoredField("path", filePath);Field fileSizeField = new LongField("size", fileSize, Field.Store.YES);Document document = new Document();document.add(fileNameField);document.add(fileContentField);document.add(filepPthField);document.add(fileSizeField);// 这里会自动创建索引indexWriter.addDocument(document);}indexWriter.close();}/*** 使用索引搜索** @Author NikoBelic* @Date 07/03/2017 19:01*/@Testpublic void testIndexSearch() throws IOException, ParseException{// 指定索引库存放路径Directory indexDir = FSDirectory.open(new File("/Users/lixiwei-mac/Documents/DataSet/lucene/index"));// 创建索引Reader、Searcher对象IndexReader indexReader = DirectoryReader.open(indexDir);IndexSearcher indexSearcher = new IndexSearcher(indexReader);// 创建查询// 方法1Query query = new TermQuery(new Term("content", "java"));// 执行查询,(查询对象,查询结果返回最大值)// 方法2// 创建分词器(必须和创建索引所用分词器一致)Analyzer analyzer = new IKAnalyzer();// 默认搜索域作用:如果搜索语法中没有指定域名,则使用默认域名搜索QueryParser queryParser = new QueryParser("filename", analyzer);// 查询语法:域名:搜索关键字Query query2 = queryParser.parse("apache");TopDocs topDocs = indexSearcher.search(query2, 5);System.out.println("查询结果的总条数:" + topDocs.totalHits);// 遍历查询结果for (ScoreDoc scoreDoc : topDocs.scoreDocs){// scoreDoc.doc = 自动生成的文档IDDocument document = indexSearcher.doc(scoreDoc.doc);System.out.println(document.get("filename"));System.out.println(scoreDoc.toString());System.out.println("======================================================");}indexReader.close();}@Testpublic void testDelIndex() throws IOException{Analyzer analyzer = new IKAnalyzer();Directory indexDir = FSDirectory.open(new File("/Users/lixiwei-mac/Documents/DataSet/lucene/index"));IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);IndexWriter indexWriter = new IndexWriter(indexDir, config);// 删除所有//indexWriter.deleteAll();// Term 词源,(域名,删除含有这些关键词的数据)indexWriter.deleteDocuments(new Term("filename", "apache"));indexWriter.commit();indexWriter.close();}/*** 更新就是按照传入的Term进行搜索,如果找到结果那么删除,将更新的内容重新生成一个Document对象* 如果没有搜索到结果,那么将更新的内容直接添加一个新的Document对象** @Author NikoBelic* @Date 07/03/2017 20:57*/@Testpublic void testUpdateIndex() throws IOException{Analyzer analyzer = new IKAnalyzer();Directory indexDir = FSDirectory.open(new File("/Users/lixiwei-mac/Documents/DataSet/lucene/index"));IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);IndexWriter indexWriter = new IndexWriter(indexDir, config);Document doc = new Document();doc.add(new TextField("filename", "更新检索测试.txt", Field.Store.YES));doc.add(new TextField("content", "文件内容测试", Field.Store.NO));doc.add(new LongField("size", 100L, Field.Store.YES));indexWriter.updateDocument(new Term("filename", "检索"), doc);indexWriter.commit();indexWriter.close();}/*** 根据索引查询,多种查询* @Author NikoBelic* @Date 08/03/2017 13:02*/@Testpublic void testSearch() throws IOException, ParseException{Directory indexDir = FSDirectory.open(new File("/Users/lixiwei-mac/Documents/DataSet/lucene/index"));IndexReader indexReader = DirectoryReader.open(indexDir);IndexSearcher indexSearcher = new IndexSearcher(indexReader);// 根据文本查询Query termQuery = new TermQuery(new Term("filename", "apache"));// 根据数字范围查询Query numQuery = NumericRangeQuery.newLongRange("size", 100L, 800L, true, true);// Bool查询BooleanQuery boolQuery = new BooleanQuery();boolQuery.add(termQuery, BooleanClause.Occur.MUST); // 独自使用MUST_NOT没有任何意义boolQuery.add(numQuery, BooleanClause.Occur.MUST);// 查询所有文档MatchAllDocsQuery matchAllDocsQuery = new MatchAllDocsQuery();// 多个域的查询,或 关系String[] fields = {"filename", "content"};MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());Query multiFieldQuery = multiFieldQueryParser.parse("apache");//TopDocs topDocs = indexSearcher.search(boolQuery, 10);//TopDocs topDocs = indexSearcher.search(matchAllDocsQuery, 10);TopDocs topDocs = indexSearcher.search(multiFieldQuery, 10);System.out.println("符合条件的文档数:" + topDocs.totalHits);for (ScoreDoc scoreDoc : topDocs.scoreDocs){Document document = indexSearcher.doc(scoreDoc.doc);System.out.println(document.get("filename"));System.out.println(document.get("size"));System.out.println("======================================================================");}}}

3.5 使用Luke工具查看索引库

搜索-Lucene学习笔记相关推荐

  1. Lucene学习笔记(1)

    Lucene学习笔记 可以搜索文本文件,理论上可以搜索任何类型的数据.只要先把数据转化为文本,就可以对数据进行索引和搜索. 使用了反向索引的机制,维护一个词/短语的表,对于每个词和短语都有一个链表描述 ...

  2. lucene学习笔记_学习Lucene

    lucene学习笔记 我目前正在与一个团队合作,开始一个基于Lucene的新项目. 虽然大多数时候我会争论使用Solr还是Elasticsearch而不是简单的Lucene,但这是一个有意识的决定. ...

  3. 黑马程序员--分布式搜索ElasticSearch学习笔记

    写在最前 黑马视频地址:https://www.bilibili.com/video/BV1LQ4y127n4/ 想获得最佳的阅读体验,请移步至我的个人博客 SpringCloud学习笔记 消息队列M ...

  4. 【web搜索】学习笔记-层次汇合聚类HAC算法

    层次汇合聚类(Hierarchical Agglomerative Clustering,HAC) 算法如下: 相关链接: 层次聚类算法原理及实现 学习笔记: 先附上上一段链接中的代码: // HAC ...

  5. Lucene 学习笔记(一)

    2019独角兽企业重金招聘Python工程师标准>>> 最近,由于需要做到搜索功能,但是搜索功能里面,涉及的关系比较复杂,如果通过sql语言来查询,效率十分低下,所以便开始研究了下j ...

  6. Lucene学习笔记

    全文检索概述 数据分类 结构化数据:具有固定格式或者长度有限的数据,例如数据库中的表.[SQL语句] 非结构化数据:与结构化数据对立,例如:邮件.网页.word文档.[数据扫描.全文检索] 半结构化数 ...

  7. 超参数搜索——初始学习率搜索的学习笔记

    1 概述 由于南溪只有一块2080Ti,所以暂时不会考虑用强化学习的方法来做~ 南溪目前想要学习的超参数搜索算法有: 网格搜索 随机搜索 贝叶斯搜索 粒子群算法 进化算法 遗传算法 (7. 强化学习) ...

  8. Lucene学习笔记:Field.Store.* 域存储选项

    2019独角兽企业重金招聘Python工程师标准>>> Store.YES: 指定存储域值.该情况下,原始的字符串值全部都被保存在索引中,并可以由IndexReader类恢复.该选项 ...

  9. 遗传算法与直接搜索工具箱学习笔记 -----从直接搜索算法开始

    一.什么是直接搜索算法 什么是直接搜索算法?这个是我们将面对的第一个问题,如果连直接搜索是什么都不知道,还谈什么应用与解决问题呢? 直接搜索算法是一种不需要任何关于目标函数梯度信息的最优化方法.与传统 ...

最新文章

  1. 检索数据表中重复的记录
  2. Spring-IoC容器
  3. 在Qt在GUI程序里显示控制台界面
  4. Android 4.4 Kitkat 使能有线网络 Ethernet
  5. CodeForces 361B Levko and Permutation
  6. mac预装的php路径,Mac使用系统自带php和Apache
  7. 【Linux使用】Centos 7安装图形界面/切换文本界面与图形界面
  8. pandas Series 判断每个元素是否包含某个子串
  9. RedHat Linux 5企业版开启VNCSERVER远程桌面功能[转]
  10. 【每日算法Day 99】你们可能不知道只用20万赢到578万是什么概念
  11. 鸟哥的Linux私房菜第零章
  12. 千兆2光4电工业级光纤自愈环网交换机ERPS环网交换机
  13. AtCoder Beginner Contest 167 Solution
  14. 数学7大定理比较,五点(驻、极、最、拐、间)比较,求极值问题(求根验证负数形式)
  15. 各种Hash函数和代码
  16. VR、AR和MR这些技术的区别
  17. 分享一个非常厉害的md5 解密网站
  18. windows电脑重装系统步骤、cmd常用命令等
  19. 别忘记 DNS 服务器的安全性
  20. 马化腾:搜索、电子商务硬仗一定要坚持打

热门文章

  1. 使用cygwin X server实现Linux远程桌面 (for windows)
  2. 不重装修复系统并恢复windows用户配置文件,适用于window 11 WSA出错后的dll文件缺失、.net framework缺失或者其他类似系统恢复后尽可能想恢复用户配置的场景
  3. linux php mkfifo,Linux进程间通信(四):命名管道 mkfifo()、open()、read()、close() - 52php - 博客园...
  4. mysql ump_UMP认识:(一)系统架构
  5. Jenkins 安装教程
  6. RedHat Linux 调整显示 分辨率 方法
  7. Rasa课程、Rasa培训、Rasa面试、Rasa实战系列之FormAction(三)
  8. CentOS上PHP源码安装和配置
  9. SDE DPM (随机微分方程导出的diffusion model)
  10. 微信小程序流量主如何开通赚钱主要看你的创意够不够