一,什么是Lucene

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的  架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。说白了就是一个做索引的开源框架。

 二,如何使用Lucene

我使用的是lucene6.6的版本,以后可能有新版本的出现,关于lucene6.6和4.x版本是不同的,使用时需要注意,下面我就来说下lucene的使用方法以及不同

lucene6.6要求jdk必须是1.8的版本,不然会报错,关于错误原因。我的博客有,其实你换下jdk就行了,下面我就直接贴个代码,然后说下不同的地方,以及使用要注 意的地方

========================================================分割线====================================================================

 /*** 使用IndexWrite向索引库中写入数据* Ctrl+T显示某个类的继承结构* @throws IOException */@Testpublic void CreateIndex() throws IOException{//索引存放的位置,设置在当前目录中Directory directory = FSDirectory.open(Paths.get("indexDir/"));//添加Lucene的版本Version version = Version.LUCENE_6_6_0;//创建lucene的分词器,主要用于进行分词,比如识别你好,中国,甚至一些以前没有,但现在出先的词Analyzer analyzer = new StandardAnalyzer(); //创建索引写入配置IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);//创建索引写入对象IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);//创建Document对象,存储索引Document doc = new Document();//创建字段用于存储数据/*** @param:name:字段名 * @param:value:字段值 * @param:store:是否存储 */int iD = 6;Field id = new IntPoint("id",iD);Field storeField = new StoredField("id", iD);Field title = new StringField("title","ImportNew - 专注Java & Android 技术分享",Store.YES);Field content = new TextField("content","ImportNew 是一个专注于 Java & Android 技术分享的博客,为Java 和 Android开发者提供有价值的内容。包括:Android开发与快讯、Java Web开发和其他的Java技术相关的",Store.YES);//将字段加入到doc中doc.add(id);doc.add(title);doc.add(content);doc.add(storeField);//将doc对象保存到索引库中indexWriter.addDocument(doc);//关闭流indexWriter.close();}/*** @throws IOException * */@Testpublic void SelectIndex() throws IOException{//索引存放的位置 Directory directory = FSDirectory.open(Paths.get("indexDir/"));//创建索引的读取器IndexReader indexReader = DirectoryReader.open(directory);//创建一个索引的查找器,来检索索引库IndexSearcher indexSearcher = new IndexSearcher(indexReader);//这是一个条件查询的api,用于添加条件Term term = new Term("title","ImportNew - 专注Java & Android 技术分享");TermQuery termQuery = new TermQuery(term);//搜索先搜索索引库//返回符合条件的前100条记录TopDocs topDocs =  indexSearcher.search(termQuery, 100);//打印查询到的记录数System.out.println("总记录数:"+topDocs.totalHits);//得到得分文档数组ScoreDoc scoreDocs[] = topDocs.scoreDocs;//遍历数组,返回一个击中for(ScoreDoc scoreDoc : scoreDocs){int docID = scoreDoc.doc;//取得对应的文档对象Document document = indexSearcher.doc(docID);System.out.println(document.get("id"));System.out.println(document.get("title"));System.out.println(document.get("content"));}}

代码说明:

使用lucene离不开核心的两个核心的api,indexWriter 和 indexSearcher ,上面已经给出了如何创建indexWriter和indexSearcher方法,然后说下不同的lucene6.6和4.4不同的地方,lucene6.6不能在使用new File(Path)的方式来传递路径了,而是使用Path类,但是这个Path是个接口,不能new,你需要使用Paths这个工具类,使用get(uri)方法传入路径,还有lucene6.6不需要,你再传递版本信息,即那个Version.66这个参数不在需要,indexWriter这个api,主要完成向索引库写入数据,删除数据,更新数据

你需要将存入的数据,放入一个叫字段的对象中,但是Int这种数字类型,没有IntField这个api了,取而代之是IntPoint这个api,你需要

把你的数据存入到Intpoint中,才能存入到索引库中,同时IntPoint没有Store.YES这个属性,这个属性表示是否将字段存入索引库中

由于没有该属性,所以我们需要在创建一个字段StoredField,这个字段表示那个数据是否要被存入索引库,创建该字段,将你的数据放进去,在来如果你要实现索引库对你的这个字段进行排序你还要创建一个NumericDocValuesField字段,不然会出现unexpected docvalues type NONE for field 'id'错误,最后需要将这些字段放入一个Document对象中,才能存入索引库,document就像数据库中的一张表,存放多个字段的数据,还有如果你想讲indexWriter变成一个工具类方法,返回indexWriter话,注意,indexWriterConfig,要保证每产生一个indexWriter就要产生一个indexWriterConfig,不然会报indexWriterConfig不能share的错误

接下来说下IndexSearcher,这个Api主要用来做查询的操作,上面的demo说明了如何用一个词条进行查询,还有很多查询方式,下面再说,注意返回的是一个ScoreDocs,表示命中了多少个数据,最后使用docID,查询,返回document,相当于表查询一样,Term相当于查询条件,整个操作像是select * from document where id=?这样的,下面给这个图,解释下索引库的结构

三,索引库的结构

索引库包含数据区和索引目录区,查询时,通过查询索引目录看能命中几个数据区的document对象,来进行查询的

四,查询的方式和排序

lucene6.6不在支持过滤这种方式,改为使用查询代替过滤,当然查询本身也能过滤的。下面介绍

1.sort(排序),代码如下

public static void main(String[] args) throws Exception {testSearcher("张总");}public static void testSearcher(String keywords) throws Exception{IndexSearcher indexSearcher = LuceneUtil.getIndexSearcher();//创建需要用于查询的字段数组String[] fields = {"title"};//创建查询用的类QueryParser queryParser = new MultiFieldQueryParser(fields, LuceneUtil.getAnalyzer());//查询符合关键字的数据Query query = queryParser.parse(keywords);//开始插叙//创建排序字段,升序 // SortField sortField = new SortField("id", Type.INT);//创建排序字段,降序 SortField sortField = new SortField("id", Type.INT,true);//创建一个Sort排序Sort sort = new Sort();//添加排序条件sort.setSort(sortField);TopDocs topDocs = indexSearcher.search(query, 100,sort);System.out.println("总记录数:"+topDocs.totalHits);List<Article> list = new ArrayList<Article>();//返回击中ScoreDoc[] scoreDocs = topDocs.scoreDocs;//int result  = (start+rows)<(scoreDocs.length)?(start+rows):(scoreDocs.length);//如果start+rowsVSscoreDocs.length的话,返回较小值for(ScoreDoc scoreDoc : scoreDocs){Document document = indexSearcher.doc(scoreDoc.doc);System.out.println(document.get("id"));}}

主要是看Sort这个对象的使用,在,search()这个方法调用时传入排序条件注意,之前说的,要让该字段支持排序,要使用 NumericDocValuesField字段,针对IntPoint这种格式数据使用。

2.接下来说查询如下

 public static void main(String[] args) throws Exception {//第一种查询TermQuery//       Query query = new TermQuery(new Term("author","张三"));
//          testSearcher(query);//第二种查询 字符串查询//String fields []={"author"};////QueryParser queryParser=new MultiFieldQueryParser(LuceneUtils.getMatchVersion(),fields,LuceneUtils.getAnalyzer());//Query query=queryParser.parse("毕加索");//第三种查询,查询所有//         Query query = new MatchAllDocsQuery();
//        testSearcher(query);//第四种查询,范围查询,可以使用次查询来替代过滤器(lucene6.6不支持过滤)//Query query = IntPoint.newRangeQuery("id", 1, 10);//testSearcher(query);/*** 第五种查询,通配符拆查询* ?代表单个任意字符* *代表多个任意字符*/// Query query = new WildcardQuery(new Term("title","luce*"));//testSearcher(query);//第六种查询,模糊查询/*** 1.需要根据条件查询* * 2.最大可编辑数,取值范围0,1,2* 允许我的查询条件的值,可以错误几个字符* */Query query = new FuzzyQuery(new Term("author","欧阳夏文某小"),1);/**
* 第七种查询,短语查询
* @param slop:设置两个短语之间的最大间隔数,设置的间隔数越大,他能匹配的结果就越多,性能就越慢
* @param field:设置查找的字段
* @param terms:设置查找的短语,是一个可变长的数组
* (lucene4.4是用add方法来添加短语,6.6通过构造函数)
*/
//PhraseQuery query =new PhraseQuery(11,"title", new String[]{"lucene","全"});
/**
* 第八种查询,布尔查询(类似于sql语句中的 and,or等查询方式)
*
* (和lucene4.4使用方式有些区别,主要在于不能直接创建BooleanQuery,而是要创建BooleanQuery.Builder,)
*/
BooleanQuery.Builder booQuery = new BooleanQuery.Builder();
//范围查询id从0-10
Query query1 =  IntPoint.newRangeQuery("id", 1, 10);
Query query2 = IntPoint.newRangeQuery("id", 5, 15);
booQuery.add(query1, Occur.MUST);
booQuery.add(query2,Occur.MUST_NOT);
//使用build方法返回BooleanQuery对象
Query query = booQuery.build();
testSearcher(query);
}public static void testSearcher(Query query) throws Exception{IndexSearcher indexSearcher = LuceneUtil.getIndexSearcher();TopDocs topDocs = indexSearcher.search(query, 100);System.out.println("总记录数:"+topDocs.totalHits);List<Article> list = new ArrayList<Article>();//返回击中ScoreDoc[] scoreDocs = topDocs.scoreDocs;for(ScoreDoc scoreDoc : scoreDocs){Document document = indexSearcher.doc(scoreDoc.doc);System.out.println(document.get("id"));System.out.println(document.get("title"));System.out.println(document.get("content"));System.out.println(document.get("author"));System.out.println(document.get("link"));}}

主要是api,不多说了,提下StringField和TextField在查询时的区别,StringField查询时必须是全部内容,比如author,你给他一个张,是查不出结果了,必须是全部内容"张三",而TextField则是可以的,

五,索引库的优化

1.使用lucene的api优化,代码如下

 public void testOptimise1() throws Exception{//可以通过indexWriterConfig这个对象来进行优化。。。//在lucene4.0之后的版本会对索引进行自动的优化。。。//改配置即可Directory directory = FSDirectory.open(Paths.get(Contants.File_Path));IndexWriterConfig indexWriterConfig = new IndexWriterConfig(LuceneUtil.getAnalyzer());//在lucene里面都是配置,都是拖过设置对象的参数来进行配置。。/*** * MergePolicy设置合并规则* */LogDocMergePolicy mergePolicy  = new LogDocMergePolicy();/*** * 1.mergeFactor* * 当这个值越小,更少的内存被运用在创建索引的时候,搜索的时候越快,创建索引的时候越慢。。* 当这个值越大,更多的内存被运用在创建索引的时候,搜索的时候越慢,创建索引的时候越快。。* *  smaller value   2 < smaller<10*  big    value   big>10* *///设置索引的合并因子。。。mergePolicy.setMergeFactor(6);indexWriterConfig.setMergePolicy(mergePolicy);IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);}

2.排除停用词,排除停用,被分词过滤掉,词就不会建立索引,索引文件就会变小,这样索引就会变得快。(停用词如:的,了,吧,英语有:with,a,he,she这些)

3.将索引数据分区存放

类似百度有,贴吧,新闻,网页,音乐不同索引区

4.使用索引放到内存中提高索引效率

因为项目一旦上线,基本不会停下来,可以将索引放入内存提高效率

六.关于IKAnalyzer,

这是一个支持中文分词的工具包 ,支持扩展自己的词典和停用词

需要使用更新的版本,老版本不支持

下载地址:http://download.csdn.net/detail/k_122/9915646。对不起,我很穷,所以需要积分下载

七,关于高亮显示关键词

还要补充一些东西,查询BooleanQuery(布尔查询)和(PhraseQuery)短语查询,这两个和4.4版本的使用方式改变了不少

(我可是找了半天才弄好,技术不好啊!) 查询代码我放在上面的查询中了,你可以自己看,下面我说下高亮,一如既往的贴

代码

 IndexSearcher indexSearcher = LuceneUtil.getIndexSearcher();//创建需要用于查询的字段数组String[] fields = {"title","content"};//创建查询用的类QueryParser queryParser = new MultiFieldQueryParser(fields, LuceneUtil.getAnalyzer());//查询符合关键字的数据Query query = queryParser.parse("张");//格式化高亮的字符串Formatter formatter  = new SimpleHTMLFormatter("<font color='red'>", "</font>");//query里面的条件,条件里面有搜索关键词Scorer fragmentScorer = new QueryScorer(query);//构建高亮插寻/*** 1.需要高亮什么颜色* 2.将那些关键词进行高亮*/Highlighter highlighter  = new Highlighter(formatter, fragmentScorer);//开始插叙TopDocs topDocs = indexSearcher.search(query,100);System.out.println("总记录数:"+topDocs.totalHits);List<Article> list = new ArrayList<Article>();//返回击中ScoreDoc[] scoreDocs = topDocs.scoreDocs;//如果start+rowsVSscoreDocs.length的话,返回较小值for(ScoreDoc scoreDoc:scoreDocs){Article article = new Article();int docID = scoreDoc.doc;//System.out.println("docuemntID======="+docID);Document document=indexSearcher.doc(docID);String title = document.get("title");String content = document.get("content");System.out.println("没有高亮的title:"+title);System.out.println("没有高亮的content:"+content);//将某段文本进行高亮,返回高亮的结果String highTitle = highlighter.getBestFragment(LuceneUtil.getAnalyzer(), "title",title);String highContent= highlighter.getBestFragment(LuceneUtil.getAnalyzer(), "content",content);//打印高亮后字符串if(highTitle==null){highTitle=title;}if(highContent==null){highContent=content;}System.out.println("高亮后字符串 title:"+highTitle);System.out.println("高亮后字符串  content:"+highContent);}}

恩,和4.4版本基本没区别,主要是导入jar包 :lucene-highlighter-6.6.0.jar和lucene-memory-6.6.0.jar,api的使用

代码中有,其实他就是在关键词那套个html标签而已。

Lucene6.6的介绍和使用相关推荐

  1. Lucene6.6.0 案例与学习路线

    之前在学习Lucene这个全文检索工具,为项目搜索引擎的开发打下基础.在这里先分享一下关于Lucene的学习心得. 核心的学习流程是:索引文件格式--索引创建过程--检索流程. 1.首先建议参看这篇精 ...

  2. Lucene6入门教程(一)简介和学习流程

    工作中需要用到Lucene6这个全文检索工具,为项目的开发打下基础.花了比较多的时间熟悉了Lucene,原理,一些网上的案例,以及基本的API使用等,在这里给大家分享一下我关于Lucene6.4.1的 ...

  3. 简单介绍互联网领域选择与营销方法

    在我看来,互联网领域的选择是"安家",而营销方法的不同则表现了"定家"的方式多种多样,只有选对了,"家"才得以"安定". ...

  4. 常用开源协议介绍以及开源软件规范列表

    1. 开源协议介绍 GPL: General Public License,开源项目最常用的许可证,衍生代码的分发需开源并且也要遵守此协议.该协议也有很多变种,不同变种要求会略微不同. MPL: MP ...

  5. python:Json模块dumps、loads、dump、load介绍

    20210831 https://www.cnblogs.com/bigtreei/p/10466518.html json dump dumps 区别 python:Json模块dumps.load ...

  6. pytorch学习笔记(九):PyTorch结构介绍

    PyTorch结构介绍 对PyTorch架构的粗浅理解,不能保证完全正确,但是希望可以从更高层次上对PyTorch上有个整体把握.水平有限,如有错误,欢迎指错,谢谢! 几个重要的类型 和数值相关的 T ...

  7. Python字节码介绍

    了解 Python 字节码是什么,Python 如何使用它来执行你的代码,以及知道它是如何帮到你的. 如果你曾经编写过 Python,或者只是使用过 Python,你或许经常会看到 Python 源代 ...

  8. Pytest - 使用介绍

    1. 概述 pytest是一个非常成熟的全功能的Python测试框架,主要特点有以下几点: 1.简单灵活,容易上手,文档丰富: 2.支持参数化,可以细粒度地控制要测试的测试用例: 3.能够支持简单的单 ...

  9. 遗传算法的简单介绍以及模式定理的简单证明

    遗传算法   遗传算法(Genetic Algorithm,GA),最早是由美国的John holland在20世纪70年代提出.算法通过模拟达尔文生物进化论的自然选择以及遗传学机理的生物进化过程来搜 ...

最新文章

  1. Mybatis操作主体流程
  2. 关于规则引擎一些基本理论的积累
  3. 剑指Offer(Java实现)扑克牌顺子
  4. redis探秘:选择合适的数据结构,减少80%的内存占用,这些点你get到了吗?
  5. oracle exp imp
  6. centos mysql 5.5.57_Centos MySQL 5.7安装、升级教程
  7. python编写性别比例失衡_性别比例失衡加剧什么情况?什么原因导致这样的结果?...
  8. java高级教程pdf_《Java高级编程实用教程》PDF 下载_IT教程网
  9. Python课堂实验-----字典攻击
  10. 网络限速软件测试大乐,宽带测速谁靠谱?网速测试软件大对比
  11. 信奥中的数学:卷积、傅立叶变换
  12. Nhanes临床数据库挖掘教程1----数据库下载
  13. 通过scheme协议启动app
  14. 京东HBase平台进化与演进
  15. 【数字图像处理】前期准备工作,库的安装(skimage库的安装!)
  16. 文件上传利器SWFUpload使用指南(转)
  17. Unity开发win10软件系列问题6: unity调用 win10 虚拟键盘tabtip.exe
  18. MySQL 安装流程 常见安装失败问题汇总!
  19. Navicat Premium使用手册
  20. 苹果闭门造车6年了!是否已经“翻车”?

热门文章

  1. vmware 16下载安装【个人实操总结版】
  2. 如何预防嗓音障碍使其健康
  3. 如果你是杰士邦的微博运营人员,面对杜蕾斯官方微博,你会采取哪些运营措施?...
  4. 贷款易、还款难,智能催收胜算几何
  5. python自动排课表_【python-leetcode207-拓扑排序】课程表
  6. Qt之QCustomPlot
  7. MOS管的知识,看这一篇就可以了
  8. vissim交通仿真实验(2)--十字信号交叉口
  9. I. 知识图谱 应用案例 --- 美团
  10. VS2010 Ultimate英文版下载