Lucene实战(二)索引业务bean以及搜索结果高亮
2014-05-05 17:42
435 查看
前言
再写不出那样的程序,看到都会红着脸躲避~~~~~
创建Field时需要指定的选项
我们在创建Field的时候,需要提供三个选项,用以指示Lucene对该FIeld的相关操作,他们分别是:
org.apache.lucene.document.field.Index——指示该Field能否被索引。有如下值(其中红色部分是常用选项):
ANALYZED——被索引,并且被分词
ANALYZED_NO_NORMS——被索引,被分词,但是不记录index-time boost信息,使用本选项后无法对该Field加权
NOT_ANALYZED——可以被索引,不分词。
NOT_ANALYZED_NO_NORMS——可以被索引,不分词,不记录boost信息,无法对该Field加权
NO——不被索引,自然也不分词了。
org.apache.lucene.document.field.Store——指示该Field的值是否被保存在索引文件中以便能够快速访问。
YES——将该Field的值存储在索引文件中。我们可以使用document.get("xxx");来快速获取内容。
NO——不存储。
org.apache.lucene.document.field.TermVector——指示是否保存该Field的关键字的位置信息。
WITH_OFFSETS——记录词语(Token)在Field值中的结束位置
WITH_POSITIONS——记录Token起始位置
WITH_POSITIONS_OFFSETS——记录Token的起始与结束位置。
NO——不记录Token的起始与结束位置
public Field(String name, String value, Store store, Index index),这是Field常用的构造方法。我们一般只需要给你Lucene指定Index和Store两个选项,TermVector采用默认即可。
下面的表格描述了Index、Store以及TermVector这三种选项组合时的情形:
确定被索引Field
这是我们用于测试的业务bean——News:
UML类图这种高大上的东西我就不贴了,呵~呵
通过对类中各个属性的分析可以得出:
author——可以被检索,但是不适合被分词,其值最好存储在索引中以便快速访问
conent——可以被检索、分词,但是由于内容过多而不适合存放在索引文件中
date——可以被检索,但是不适合被分词,其值最好存储在索引中以便快速访问,另外这个日期是有权的(即优先显示最近发生的新闻,这是个高级话题了)
id——不可以被检索、分词、但是应当放在索引文件中以便快速访问(比如根据id值去数据库里面找真正的News)
title——新闻标题,可以被检索、分词,而且适合放在索引文件中以便快速访问
url——不可以被检索、分词、但是应当放在索引文件中一遍快速访问(从而根据url值直接跳转到相关网页)
为News.java建立索引
利用Lucene高亮搜索
所谓高亮搜索,就是在搜索结果(Field值)中添加指定的HTML元素。为此需要添加lucene-highlighter-3.5.0.jar。
测试
上面的代码直接复制是跑不起来的,这里是一个我弄好的Eclipse过程,首先将IndexTestCases.java run as junit,再将SearchTestCases.java run as junit。即可看到效果。
工程下载
上面的工程中还运用了一些QueryParser的语法,其实也挺简单,但是我实在饿了,今儿到此结束吧,挺好_wawaw
注意:
这是我的项目截图,你需要添加这四个包到lib文件夹,编辑类路径,ok,搞定。
再写不出那样的程序,看到都会红着脸躲避~~~~~
创建Field时需要指定的选项
我们在创建Field的时候,需要提供三个选项,用以指示Lucene对该FIeld的相关操作,他们分别是:
org.apache.lucene.document.field.Index——指示该Field能否被索引。有如下值(其中红色部分是常用选项):
ANALYZED——被索引,并且被分词
ANALYZED_NO_NORMS——被索引,被分词,但是不记录index-time boost信息,使用本选项后无法对该Field加权
NOT_ANALYZED——可以被索引,不分词。
NOT_ANALYZED_NO_NORMS——可以被索引,不分词,不记录boost信息,无法对该Field加权
NO——不被索引,自然也不分词了。
org.apache.lucene.document.field.Store——指示该Field的值是否被保存在索引文件中以便能够快速访问。
YES——将该Field的值存储在索引文件中。我们可以使用document.get("xxx");来快速获取内容。
NO——不存储。
org.apache.lucene.document.field.TermVector——指示是否保存该Field的关键字的位置信息。
WITH_OFFSETS——记录词语(Token)在Field值中的结束位置
WITH_POSITIONS——记录Token起始位置
WITH_POSITIONS_OFFSETS——记录Token的起始与结束位置。
NO——不记录Token的起始与结束位置
public Field(String name, String value, Store store, Index index),这是Field常用的构造方法。我们一般只需要给你Lucene指定Index和Store两个选项,TermVector采用默认即可。
下面的表格描述了Index、Store以及TermVector这三种选项组合时的情形:
Store | Index | TermVector | 适用场景(适合什么样的Field) |
YES | NOT_ANALYZED_NO_NORMAS | NO | bean的ID,***号,电话号码等不可拆分的字段 |
YES | ANALYZED | WITH_POSITIONS_OFFSETS | bean的title,摘要等 |
NO | ANALYZED | WITH_POSITIONS_OFFSETS | bean的内容部分(内容较多,不适合放到索引文件的情况) |
YES | NO | NO | 需要被快速访问,但是不能被检索的Field,例如URL,文件大小等 |
这是我们用于测试的业务bean——News:
UML类图这种高大上的东西我就不贴了,呵~呵
通过对类中各个属性的分析可以得出:
author——可以被检索,但是不适合被分词,其值最好存储在索引中以便快速访问
conent——可以被检索、分词,但是由于内容过多而不适合存放在索引文件中
date——可以被检索,但是不适合被分词,其值最好存储在索引中以便快速访问,另外这个日期是有权的(即优先显示最近发生的新闻,这是个高级话题了)
id——不可以被检索、分词、但是应当放在索引文件中以便快速访问(比如根据id值去数据库里面找真正的News)
title——新闻标题,可以被检索、分词,而且适合放在索引文件中以便快速访问
url——不可以被检索、分词、但是应当放在索引文件中一遍快速访问(从而根据url值直接跳转到相关网页)
为News.java建立索引
//对JavaBean索引 public synchronized void createIndex(List<News> news){ Field idField,titleField,contentField,authorField,dateField; News n; Document doc; for(int i=0;i<news.size();i++){ n=news.get(i); idField=new Field("id",n.getId(),Store.YES,Index.NOT_ANALYZED); idField.setBoost(0.0001F); titleField=new Field("title",n.getTitle(),Store.YES,Index.ANALYZED); contentField=new Field("content",n.getContent(),Store.NO,Index.ANALYZED); authorField=new Field("author",n.getAuthor(),Store.YES,Index.NOT_ANALYZED); dateField=new Field("date",n.getDate().getTime()+"",Store.YES,Index.NO); doc=new Document(); doc.add(idField); doc.add(titleField); doc.add(contentField); doc.add(authorField); doc.add(dateField); System.out.println(n); try { indexWriter.addDocument(doc); } catch (CorruptIndexException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } try { indexWriter.commit(); } catch (CorruptIndexException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
利用Lucene高亮搜索
所谓高亮搜索,就是在搜索结果(Field值)中添加指定的HTML元素。为此需要添加lucene-highlighter-3.5.0.jar。
package org.xiaom.lucene; import java.io.File; public class NewsSearcher { public static final Version CURRENT_VERSION=Version.LUCENE_35; public static final String DEFAULT_HIGHLIGHT_STYLE_pre="<strong>";//高亮的HTML前缀 public static final String DEFAULT_HIGHLIGHT_STYLE_post="</strong>";//后缀 private NewsService newsService; private Analyzer defaultAnalyzer=new StandardAnalyzer(CURRENT_VERSION); private IndexSearcher indexSearcher; private QueryParser queryParser; private Highlighter highlighter; private Formatter formatter; public NewsSearcher(String indexPath,String pre,String post) { IndexReader reader = null; try { reader = IndexReader.open(FSDirectory.open(new File(indexPath))); indexSearcher=new IndexSearcher(reader); queryParser=new QueryParser(CURRENT_VERSION, "title", defaultAnalyzer); } catch (CorruptIndexException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //1,利用高亮前后缀初始化一个SimpleHTMLFormatter formatter=new SimpleHTMLFormatter(pre, post); } public List<News> getNewsByKeyWordsInHightLight(String keyWord){ List<News> news=new ArrayList<News>(); try { Query query=queryParser.parse(keyWord); System.out.println(query); TopDocs topDocs=indexSearcher.search(query, 100); ScoreDoc[] scoreDocs=topDocs.scoreDocs; System.err.println("totalHits:"+topDocs.totalHits); if(topDocs.totalHits>0){ //2,初始化QueryScorer与Fragmenter QueryScorer queryScorer=new QueryScorer(query); Fragmenter fragmenter=new SimpleSpanFragmenter(queryScorer); //3,初始化highlighter并设置fragmenter highlighter=new Highlighter(formatter, queryScorer); highlighter.setTextFragmenter(fragmenter); for(int i=0;i<scoreDocs.length;i++){ Document doc=indexSearcher.doc(scoreDocs[i].doc); News n=newsService.get(doc.get("id")); //4,获取加入高亮前后缀后的文本 n.setTitle(highlighter.getBestFragment(defaultAnalyzer, "title", doc.get("title"))); news.add(n); } } } catch (ParseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InvalidTokenOffsetsException e) { e.printStackTrace(); } return news; } public NewsService getNewsService() { return newsService; } public void setNewsService(NewsService newsService) { this.newsService = newsService; } @Override protected void finalize() throws Throwable { this.indexSearcher.close(); super.finalize(); } }
测试
上面的代码直接复制是跑不起来的,这里是一个我弄好的Eclipse过程,首先将IndexTestCases.java run as junit,再将SearchTestCases.java run as junit。即可看到效果。
工程下载
上面的工程中还运用了一些QueryParser的语法,其实也挺简单,但是我实在饿了,今儿到此结束吧,挺好_wawaw
注意:
这是我的项目截图,你需要添加这四个包到lib文件夹,编辑类路径,ok,搞定。
相关文章推荐
- lucene全文搜索之四:创建索引搜索器、6种文档搜索器实现以及搜索结果分析(结合IKAnalyzer分词器的搜索器)基于lucene5.5.3
- lucene全文搜索之四:创建索引搜索器、6种文档搜索器实现以及搜索结果分析(结合IKAnalyzer分词器的搜索器)基于lucene5.5.3
- Lucene —— 搜索结果高亮显示
- Lucene以及索引和搜索的流程
- Lucene 结果中搜索,多索引搜索
- Lucene.Net核心类简介,创建索引,搜索,Lucene高亮组建演示,Rss获得最新帖子,只索引帖子的有意义部分,在AddDocument之前先移除旧有文档.
- 19、学习Lucene3.5索引之高亮搜索
- 发一个Lucene 2.4.0对搜索结果高亮显示的代码
- Lucene 3.0.0 对搜索结果的高亮显示
- 01-lucene简介和索引创建以及搜索
- 关于Lucene以及索引和搜索的流程
- 【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词
- 转 lucene3搜索引擎,索引建立搜索排序分页高亮显示, IKAnalyzer分词
- 5 Lucene笔记(五):搜索结果高亮
- .net lucene 实战搜索(二)----- 基本之索引
- 使用lucene将索引结果进行高亮显示
- Lucene SandBox包中highlighter(高亮显示搜索结果包)存在的问题
- 【Lucene3.6.2入门系列】第14节_SolrJ操作索引和搜索文档以及整合中文分词
- lucene3.0+版本中文分词测试+搜索结果+创建索引测试
- 搜索学习入门--使用LuceneHighlighter高亮显示Lucene检索结果的关键词