Lucene6.6的介绍和使用
来源:互联网 发布:写c语言用什么软件 编辑:程序博客网 时间:2024/04/25 06:48
一,什么是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 */ @Test public 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 * */ @Test public 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的介绍和使用
- Lucene6的使用
- Lucene6.5.0 下中文分词IKAnalyzer编译和使用
- Lucene6.6多查询优化
- Lucene6入门教程(三)搜索和查询
- Lucene6入门教程(二)索引的创建
- Lucene6.6之多索引+排序+多查询
- lucene6.6+拼音分词+ik分词实现
- 3.创建和维护索引库(Lucene6.0.0 CRUD)
- Lucene6入门教程(一)简介和学习流程
- JNDI的介绍和使用
- Doxygen的介绍和使用
- JpGraph的介绍和使用
- 迭代器的介绍和使用
- IbatisNet的介绍和使用
- sqlite的介绍和使用
- CountDownLatch的介绍和使用
- CompletionService的介绍和使用
- 页面跳转
- Java Web--增删改查之二界面后台java代码
- Stream 中Collectors 的用法
- 动态代理与静态代理
- 版本管理工具学习随笔(一)
- Lucene6.6的介绍和使用
- 21、包含min函数的栈
- Mac通过HEXO搭建博客
- Microbiome:微生物组研究中优化方法和规避误区
- ubuntu14.04 编译安装gcc-5.3.0
- hdu 6049 Sdjpx Is Happy(区间DP+暴力枚举)
- SQL server 联合
- HashMap
- 排序——插入排序