一、Lucene基本介绍:

  • 基本信息:Lucene 是 Apache 软件基金会的一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene 的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
  • 文件结构:自上而下树形展开,一对多。

    • 索引Index:相当于库或者表。
    • 段Segment:相当于分库或者分表。
    • 文档Document:相当一条数据 ,如小说吞噬星空
    • 域Field:一片文档可以分为多个域,相当于字段,如:小说作者,标题,内容。。。
    • 词元Term:一个域又可以分为多个词元,词元是做引搜索的最小单位,标准分词下得词元是一个个单词和汉字。
  • 正向信息:
    • 索引->段->文档->域->词
  • 反向信息:
    • 词->文档。 

二、Lucene全文检索:

1、数据分类:

  • 结构化数据:数据库,固定长度和格式的数据。
  • 半结构化数据:如xml,html,等..。
  • 非结构化数据:长度和格式都不固定的数据,如文本...

2、检索过程:Luncene检索过程可以分为两个部分,一个部分是上图左侧结构化,半结构化,非结构化数据的索引建立过程,另一部分是右侧索引查询过程。

  • 索引过程:

    • 有一系列被索引文件
    • 被索引文件经过语法分析和语言处理形成一系列词(Term)。
    • 经过索引创建形成词典和反向索引表。
    • 通过索引存储将索引写入硬盘/内存。
  • 搜索过程:
    • 用户输入查询关键字。
    • 对查询语句经过语法分析和语言分析得到一系列词(Term)。
    • 通过语法分析得到一个查询树。
    • 通过索引存储将索引读入到内存。
    • 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得到结果文档。
    • 将搜索到的结果文档对查询的相关性进行排序。
    • 返回查询结果给用户。

3、反向索引:  

  luncene检索关键词,通过索引可以将关键词定位到一篇文档,这种与哦关键词到文档的映射是文档到字符串映射的方向过程,所以称之为方向索引。

4、创建索引:

  • document:索引文档,
  • 分词技术:各种分词技术,标准分词:中文分成单个汉字,英文单个单词。
  • 索引创建:得到一张索引表。

5、索引检索:

  • 四个步骤:关键词(keyword)->分词方法(analyzer)->检索索引(searchIndex)->返回结果(result)
  • 详细步骤:输入一个关键词,使用分词方法进行分词得到词元,到索引表中去检索这些词元,找到包含所有词源的文档,并将其返回。

三、Lucene的数学模型:

1、关键名词:

  • 文档:一篇文章是一篇文档。
  • 域:文档有可以分错多个域:如文档名,文档作者,文档时间,文档内容。
  • 词元:一个域可以分为多个词元,比如说文档名为中华古诗词简介,通过分词可以得到词元:中,华,古,诗,词,简,介。这个是用标准分词得到,词元是搜索的最小单位。

2、权重计算:

  • TF:Term Frequency,词元在这个文档中出现的次数,tf值越大,词越重要。
  • DF:Document Frequency,有多少文档包含这个词元,df越大,那么词就越不重要。
  • 权重计算公式:Wt,d=TFt,d * log(n/DFt),TFt,d表示词元t在文档d出现的次数,n表示文档数,DFt表示包含词元t的文档数。

3、空间向量模型:

  • 用一篇文档的每次词元的权重构成一个向量(每个词元的权重值作为向量的维度)来表示这篇文档,这样所有的文档都可以表示成一个N维的空间向量。N表示所有文档分词后的词元集合的词元总数。实例如下:
  • 检索过程:m篇文档我们得到了m个N维的空间向量,搜索词我们分词得到x个词元,计算这x个词元的权重,得到一个N维的向量XV,通过计算XV和m个N维向量的相似度(余玄夹角)来表示相关性。Lucene通过这个相关性打分机制来得到返回的文档。

四、官方示例Demo:

  • 下载源代码和jar:http://lucene.apache.org/core/
  • 核心jar包如下:
  • 运行源代码中的demo实例文件和LucenecoreAPI中示例,来看看luncene是如何创建Index和检索的。

  • 用Idea构建了一个java项目:如下所示添加这6个核心包,和示例文件。
  • IndexFiles,SearchFiles分别是遍历一个文件目录创建索引和手动输入关键词检索返回命中文件。CindexSrarch是实例一个内存索引创建并添加文档,最终检索的过程。
    1. package Test;
    2.  
    3. import org.apache.lucene.analysis.Analyzer;
    4. import org.apache.lucene.analysis.standard.StandardAnalyzer;
    5. import org.apache.lucene.document.Document;
    6. import org.apache.lucene.document.Field;
    7. import org.apache.lucene.document.TextField;
    8. import org.apache.lucene.index.DirectoryReader;
    9. import org.apache.lucene.index.IndexWriter;
    10. import org.apache.lucene.index.IndexWriterConfig;
    11. import org.apache.lucene.queryparser.classic.QueryParser;
    12. import org.apache.lucene.search.IndexSearcher;
    13. import org.apache.lucene.search.Query;
    14. import org.apache.lucene.search.ScoreDoc;
    15. import org.apache.lucene.store.Directory;
    16. import org.apache.lucene.store.RAMDirectory;
    17.  
    18. import java.io.IOException;
    19.  
    20. /**
    21. * Created by rzx on 2017/6/1.
    22. */
    23. public class CindexSearch {
    24.  
    25. public static void createIndexANDSearchIndex() throws Exception{
    26. Analyzer analyzer = new StandardAnalyzer();//标准分词器
    27. //RAMDirectory内存字典存储索引
    28. Directory directory = new RAMDirectory();
    29. //Directory directory = FSDirectory.open("/tmp/testindex");磁盘存储索引
    30.  
    31. IndexWriterConfig config = new IndexWriterConfig(analyzer);
    32. IndexWriter writer = new IndexWriter(directory,config);
    33. Document document = new Document();
    34. String text = "hello world main test";
    35. document.add(new Field("filetest",text, TextField.TYPE_STORED)); //将域field添加到document中
    36. writer.addDocument(document);
    37. writer.close();
    38.  
    39. DirectoryReader directoryReader = DirectoryReader.open(directory);
    40. IndexSearcher isearch = new IndexSearcher(directoryReader);
    41. QueryParser parser = new QueryParser("filetest",new StandardAnalyzer());
    42. Query query = parser.parse("main");//查询main关键词
    43. ScoreDoc [] hits = isearch.search(query,1000).scoreDocs;
    44. for (int i = 0; i <hits.length ; i++) {
    45. Document hitdoc =isearch.doc(hits[i].doc);
    46. System.out.print("命中的文件内容:"+hitdoc.get("filetest"));
    47. }
    48. directoryReader.close();
    49. directory.close();
    50. }
    51. public static void main(String[] args) {
    52. try {
    53. createIndexANDSearchIndex();
    54. } catch (Exception e) {
    55. e.printStackTrace();
    56. }
    57. }
    58. }

    运行结果:

  • input目录中创建了两个文件test1.txt,test2.txt,内容分别是:hello world和hello main man test。运行IndexFiles读取input目录,并自动创建一个testindex索引目录,结果如下:

  • 目录中创建了testindex文件,里面存储索引相关信息。运行SearchFiles如下:分别在控制台输入检索关键字:hello,min

五、核心类:

  • 建立索引:Analyzer,Director(RAMDirectory,FSDirectory),IndexWriterConfig,IndexWriter,Document

    1. * Analyzer analyzer = new StandardAnalyzer(); //实例化分词器
    2. * Directory directory = new RAMDirectory(); //初始化内存索引目录
    3. * Directory directory = FSDirectory.open("indexpath");//初始化磁盘存储索引
    4. * IndexWriterConfig config = new IndexWriterConfig(analyzer); //索引器配置
    5. * IndexWriter writer = new IndexWriter(directory,config); //索引器
    6. * Document document = new Document(); //初始化Document,用来存数据。
  • 查询索引:DirectoryReader,IndexSearch,QueryParser,MutilFieldQueryParser,
    1. * DirectoryReader directoryReader = DirectoryReader.open(directory); //索引目录读取器
    2. * IndexSearcher isearch = new IndexSearcher(directoryReader); //索引查询器
    3. *多种检索方式:
    4. * QueryParser单字段<域>绑定:
    5. QueryParser qparser = new QueryParser("filed",new StandardAnalyzer()); //查询解析器:参数Field域,分词器
    6. Query query = qparser.parse("main") //查询关键词
    7. * MultiFieldQueryParser多字段<域>绑定():
    8. QueryParser qparser2 = new MultiFieldQueryParser(new String[]{"field1","field2"},new StandardAnalyzer());//多字段查询解析器
    9. Query query = qparser2.parse("main") //查询关键词
    10. * Term绑定字段<域>查询:new Term(field,keyword);
    11. Term term =new Term("content","main");
    12. Query query = new TermQuery(term);
    13. *更多方法:参照http://blog.csdn.net/chenghui0317/article/details/10824789
    14. * ScoreDoc [] hits = isearch.search(query,1000).scoreDocs; //查询你命中的文档以及评分和所在分片
  • 高亮显示:SimpleHTMLFormatter,Highlighter,SimpleFragmenter
    1. SimpleHTMLFormatter formatter=new SimpleHTMLFormatter("<b><font color='red'>","</font></b>");
    2. Highlighter highlighter=new Highlighter(formatter, new QueryScorer(query));
    3. highlighter.setTextFragmenter(new SimpleFragmenter(400));
    4. String conten = highlighter.getBestFragment(new StandardAnalyzer(),"contents","hello main man test");
  • 内置分词器:Lucene中实现了很多分词器,有针对性的应用各个场景和各种语言。
    1. QueryParser qparser = new QueryParser("content",new SimpleAnalyzer());
    2. QueryParser qparser = new QueryParser("content",new ClassicAnalyzer());
    3. QueryParser qparser = new QueryParser("content",new KeywordAnalyzer());
    4. QueryParser qparser = new QueryParser("content",new StopAnalyzer());
    5. QueryParser qparser = new QueryParser("content",new UAX29URLEmailAnalyzer());
    6. QueryParser qparser = new QueryParser("content",new UnicodeWhitespaceAnalyzer());
    7. QueryParser qparser = new QueryParser("content",new WhitespaceAnalyzer());
    8. QueryParser qparser = new QueryParser("content",new ArabicAnalyzer());
    9. QueryParser qparser = new QueryParser("content",new ArmenianAnalyzer());
    10. QueryParser qparser = new QueryParser("content",new BasqueAnalyzer());
    11. QueryParser qparser = new QueryParser("content",new BrazilianAnalyzer());
    12. QueryParser qparser = new QueryParser("content",new BulgarianAnalyzer());
    13. QueryParser qparser = new QueryParser("content",new CatalanAnalyzer());
    14. QueryParser qparser = new QueryParser("content",new CJKAnalyzer());
    15. QueryParser qparser = new QueryParser("content",new CollationKeyAnalyzer());
    16. QueryParser qparser = new QueryParser("content",new CustomAnalyzer(Version defaultMatchVersion, CharFilterFactory[] charFilters, TokenizerFactory
    17. tokenizer, TokenFilterFactory[] tokenFilters, Integer posIncGap, Integer offsetGap));
    18. QueryParser qparser = new QueryParser("content",new SmartChineseAnalyzer());//中文最长分词

六、高亮示例:

  • 读取indexfile创建的索引testindex,并查询关键字main并高亮。出现异常:Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/lucene/index/memory/MemoryIndex需要导入:lucene-memory-6.5.1.jar,这个包用来处理存储位置的偏移量,可以让我们在文本中定位到关键词元.
    1. public static void searchByIndex(String indexFilePath,String keyword) throws ParseException, InvalidTokenOffsetsException {
    2. try {
    3. String indexDataPath="testindex";
    4. String keyWord = "main";
    5. Directory dir= FSDirectory.open(new File(indexDataPath).toPath());
    6. IndexReader reader= DirectoryReader.open(dir);
    7. IndexSearcher searcher=new IndexSearcher(reader);
    8. QueryParser queryParser = new QueryParser("contents",new StandardAnalyzer());
    9. Query query = queryParser.parse("main");
    10.  
    11. TopDocs topdocs=searcher.search(query,10);
    12. ScoreDoc[] scoredocs=topdocs.scoreDocs;
    13. System.out.println("最大的评分:"+topdocs.getMaxScore());
    14. for(int i=0;i<scoredocs.length;i++){
    15. int doc=scoredocs[i].doc;
    16. Document document=searcher.doc(doc);
    17. System.out.println("=====================================");
    18. System.out.println("关键词:"+keyWord);
    19. System.out.println("文件路径:"+document.get("path"));
    20. System.out.println("文件ID:"+scoredocs[i].doc);
    21. //开始高亮
    22. SimpleHTMLFormatter formatter=new SimpleHTMLFormatter("<b><font color='red'>","</font></b>");
    23. Highlighter highlighter=new Highlighter(formatter, new QueryScorer(query));
    24. highlighter.setTextFragmenter(new SimpleFragmenter(400));
    25. String conten = highlighter.getBestFragment(new StandardAnalyzer(),"contents","hello main man test");
    26. //String conten = highlighter.getBestFragment(new StandardAnalyzer(),"contents",document.get("content"));
    27.  
    28. System.out.println("文件内容:"+conten);
    29. System.out.println("相关度:"+scoredocs[i].score);
    30. }
    31. reader.close();
    32. } catch (IOException e) {
    33. e.printStackTrace();
    34. }
    35. }

    输出结果:

源代码:https://codeload.github.com/NextNight/luncene6.5.1Test/zip/master

[Lucene]-Lucene基本概述以及简单实例的更多相关文章

  1. Flume概述和简单实例

    Flume概述 Flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统.支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方( ...

  2. JMeter学习-008-JMeter 后置处理器实例之 - 正则表达式提取器(一)概述及简单实例

    上文我们讲述了如何对 HTTP请求 的响应数据进行断言,以判断响应是否符合我们的预期,敬请参阅:JMeter学习-007-JMeter 断言实例之一 - 响应断言 那么我们如何获取 HTTP请求 响应 ...

  3. lucene构建restful风格的简单搜索引擎服务

    来自于本人博客: lucene构建restful风格的简单搜索引擎服务 本人的博客如今也要改成使用lucene进行全文检索的功能,因此在这里把代码贴出来与大家分享 一,文件夹结构: 二,配置文件: 总 ...

  4. ajax原理总结附简单实例及其优点

    在工作中用了Ajax N多次了,也看过一些相关方面的书籍,也算是认识了它,但是一直没有认真总结和整理过相关的东东,失败! 近有闲情,将之总结如下: [名称] Ajax是Asynchronous Jav ...

  5. 1.搜索引擎的历史,搜索引擎起步,发展,繁荣,搜索引擎的原理,搜索技术用途,信息检索过程,倒排索引,什么是Lucene,Lucene快速入门

     一: 1  搜索引擎的历史 萌芽:Archie.Gopher Archie:搜索FTP服务器上的文件 Gopher:索引网页 2  起步:Robot(网络机器人)的出现与spider(网络爬虫) ...

  6. Spring boot项目搭建及简单实例

    Spring boot项目搭建 Spring Boot 概述 Build Anything with Spring Boot:Spring Boot is the starting point for ...

  7. Hibernate(二)__简单实例入门

    首先我们进一步理解什么是对象关系映射模型? 它将对数据库中数据的处理转化为对对象的处理.如下图所示: 入门简单实例: hiberante 可以用在 j2se 项目,也可以用在 j2ee (web项目中 ...

  8. 最新 Eclipse IDE下的Spring框架配置及简单实例

    前段时间开始着手学习Spring框架,又是买书又是看视频找教程的,可是鲜有介绍如何配置Spring+Eclipse的方法,现在将我的成功经验分享给大家. 本文的一些源代码来源于码农教程:http:// ...

  9. 修改js confirm alert 提示框文字的简单实例

    修改js confirm alert 提示框文字的简单实例: <!DOCTYPE html> <html> <head lang="en"> & ...

随机推荐

  1. Java中的集合与线程的Demo

    一.简单线程同步问题 package com.ietree.multithread.sync; import java.util.Vector; public class Tickets { publ ...

  2. DFB系列 之 Clear清空surface缓存

    1. 函数原型解析 函数声明: DFBResult Clear (     IDirectFBSurface    *  thiz,      u8     r,      u8     g,     ...

  3. Java:构造器,构造代码块,静态代码块的执行顺序

    1.构造器:与类同名且没有返回值,用来初始化类属性: 构造器又分为无参构造器和有参构造器 1.1:无参构造器 public class Contruction{ ...属性... public Con ...

  4. webstorm html碎片整理功能

    我们用字符串形式写html模板时,或者向某标签添加html内容时,如下,如果这个str更加的长,一旦里面少了一个单引号,少了一个加号,基本报错还看不懂,一脸懵逼... // 假定后台传给我们的数据为 ...

  5. abstract、virtual、sealed

    abstract与virtual前必有public 1.abstract,抽象 1)只要使用到了abstract定义了方法,那么类就一定得用abstract定义,public abstract,只有抽 ...

  6. ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统

    为什么使用 Jwt 最近,移动开发的劲头越来越足,学校搞的各种比赛都需要用手机 APP 来撑场面,所以,作为写后端的,很有必要改进一下以往的基于 Session 的身份认证方式了,理由如下: 移动端经 ...

  7. 基于require+knockout的webapp结构设计

    *********************************************************************************** 一.项目结构: Webapp - ...

  8. poj3067 Japan 树状数组求逆序对

    题目链接:http://poj.org/problem?id=3067 题目就是让我们求连线后交点的个数 很容易想到将左端点从小到大排序,如果左端点相同则右端点从小到大排序 那么答案即为逆序对的个数 ...

  9. Java学习笔记——设计模式之一.简单工厂

    蜀道之难.难于上青天,侧身西望长咨嗟 --蜀道难 设计模式第一篇,简单工厂. 定义Operation类 package cn.no1.simplefactory; public abstract cl ...

  10. ZooKeeper实践:(2)集群管理

    前言: 随着业务的扩大,用户的增多,访问量的增加,单机模式已经不能支撑,从而出现了从单机模式->垂直应用模式->集群模式,集群模式诞生了,伴随着一堆问题也油然而生,Master怎么选举,机 ...