JAVA_WEB项目之Lucene实现检索结果排序和关键字在索引库中多字段查询结果进行高亮显示
2014-07-24 17:15
1096 查看
上一篇介绍了JAVA_WEB项目之Lucene使用中文分词器IKAnalyzer3.2.8,接下来对上一篇的代码实现排序的效果和关键字在索引库中多字段查询结果进行高亮显示。
首先是排序的效果:
Goods类,LuceneUtil类,ConfigureLucene类,测试类等的代码和上一篇的一样,只有HelloWordLucene里面的查询代码不一样。
效果显示:
首先我们写一个高亮的工具类HighlighterUtil:
修改上一篇DocumentUtil的代码如下:
高亮的实现类:
测试类:
查询的结果:
我们可以发现高亮的html代码包裹着关键字。
首先是排序的效果:
Goods类,LuceneUtil类,ConfigureLucene类,测试类等的代码和上一篇的一样,只有HelloWordLucene里面的查询代码不一样。
/** * 根据指定的条件查询, * @param name 指定的关键字 * @return 封装了goods对象的list集合 */ public List<Goods> queryGoods(String name){ List<Goods> goodsList=new ArrayList<Goods>(); //创建查询对象 IndexSearcher searcher=null; try { searcher=LuceneUtil.getIndexSearcher(); // 指定查询的关键字到索引库查询 Query query=IKQueryParser.parse("name", name); /** * 根据给定的关键字查询,与索引库Term去匹配,5代表: 期望返回的结果数 * 第一次查询: indexSearcher.search 只能获取文档的索引号和匹配的数量 * 返回的结果是TopDoc类型 * totalHits: 命中数, 数组的长度,后面用来做分页 * ScoreDoc[]: 存储匹配的文档编号的数组 * Score: 文档的积分,按照命中率自动算出来 * Doc:当前文档的编号 */ //增加排序的效果 /*对象查询的结果进行排序: Lucene排序有两种: 命中率排序, 根据字段排序 *注意 这两种排序方式不互斥的,如果选择按字段排序命中率是不会被计算出来, 但是字段排序本身可以支持多字段 *被排序的字段,和被删除更新一样 字段必须创建索引 * true代表的是降序 */ Sort sort=new Sort(new SortField("id",SortField.INT, true),new SortField("price", SortField.DOUBLE,true)); TopDocs topDocs= searcher.search(query, null, 5, sort); // 此变量/每页显示的记录数就是总页数 System.out.println("真正命中的结果数:" + topDocs.totalHits); // 返回的是符合条件的文档编号,并不是文档本事 ScoreDoc scoreDocs[]= topDocs.scoreDocs; for(int i=0;i<scoreDocs.length;i++){ ScoreDoc scoreDoc= scoreDocs[i]; System.out.println("真正的命中率:"+scoreDoc.score); System.out.println("存储的是文档编号:"+scoreDoc.doc); Document doc= searcher.doc(scoreDoc.doc); System.out.println(doc.get("id")); System.out.println(doc.get("name")); System.out.println(doc.get("price")); System.out.println(doc.get("remark")); System.out.println("---------"); // Goods goods=new Goods(); // goods.setId(Integer.parseInt(doc.get("id"))); // goods.setName(doc.get("name")); // goods.setPrice(Double.parseDouble(doc.get("price"))); // goods.setRemark(doc.get("remark")); goodsList.add(DocumentUtil.documentToGoods(doc)); } } catch (Exception e) { // TODO Auto-generated catch block throw new RuntimeException(e); } return goodsList; }
效果显示:
商品编号:13,商品名称:IBM Computer12 ,商品价格:3333.9,商品的详细信息:null 商品编号:12,商品名称:IBM Computer12 ,商品价格:2333.9,商品的详细信息:null 商品编号:11,商品名称:IBM Computer12 ,商品价格:2333.9,商品的详细信息:null 商品编号:11,商品名称:IBM是全球知名的电脑厂商,现在已经专门做服务的,已经把生产版权转给联想了,商品价格:2333.9,商品的详细信息:null接下来实现关键字查询高亮的效果的代码:
首先我们写一个高亮的工具类HighlighterUtil:
package com.shop.demo2; import java.io.IOException; import org.apache.lucene.search.Query; import org.apache.lucene.search.highlight.Formatter; import org.apache.lucene.search.highlight.Highlighter; import org.apache.lucene.search.highlight.InvalidTokenOffsetsException; import org.apache.lucene.search.highlight.QueryScorer; import org.apache.lucene.search.highlight.Scorer; import org.apache.lucene.search.highlight.SimpleFragmenter; import org.apache.lucene.search.highlight.SimpleHTMLFormatter; public class HighlighterUtil { private HighlighterUtil(){} private static Formatter formatter=null; static{ formatter=new SimpleHTMLFormatter("<font color='red'>", "</font>"); } public static String setHighlighterText(Query query,String iniData,int length){ String result=null; try { // query对象中有查询的关键字,字段匹配关键字的内容将会高亮 Scorer scorer=new QueryScorer(query); // 实现高亮的工具类 Highlighter highlighter=new Highlighter(formatter, scorer); // 设置高亮后的字符长度 highlighter.setTextFragmenter(new SimpleFragmenter(length)); //给指定字段进行高亮效果 result= highlighter.getBestFragment(ConfigureLucene.getAna(), null,iniData); if(result==null){ if(iniData.length()>length){ result=iniData.substring(0, length); }else{ result=iniData; } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } }
修改上一篇DocumentUtil的代码如下:
package com.shop.demo2; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.Field.Index; import org.apache.lucene.document.Field.Store; public class DocumentUtil { private DocumentUtil(){} /** * 把goods对象转为document对象 */ public static Document goodsToDocument(Goods goods){ //把goods对象转为document Document doc=new Document(); doc.add(new Field("id", goods.getId().toString(), Store.YES, Index.NOT_ANALYZED)); doc.add(new Field("name", goods.getName(), Store.YES, Index.ANALYZED)); doc.add(new Field("price", goods.getPrice().toString(), Store.YES, Index.NOT_ANALYZED)); doc.add(new Field("remark", goods.getRemark(), Store.YES, Index.ANALYZED)); return doc; } /** * 把document对象转为goods对象 */ public static Goods documentToGoods(Document doc){ Goods goods=new Goods(); goods.setId(Integer.parseInt(doc.get("id"))); goods.setName(doc.get("name")); goods.setPrice(Double.parseDouble(doc.get("price"))); goods.setRemark(doc.get("remark")); return goods; } }
高亮的实现类:
/** * 根据指定的条件查询, * @param keyword 指定的关键字 * @return 封装了goods对象的list集合 */ public List<Goods> queryGoods(String keyword){ List<Goods> goodsList=new ArrayList<Goods>(); //创建查询对象 IndexSearcher searcher=null; try { searcher=LuceneUtil.getIndexSearcher(); // 指定查询的关键字到索引库查询 Query query=IKQueryParser.parseMultiField(new String[]{"name","remark"}, keyword); /** * 根据给定的关键字查询,与索引库Term去匹配,5代表: 期望返回的结果数 * 第一次查询: indexSearcher.search 只能获取文档的索引号和匹配的数量 * 返回的结果是TopDoc类型 * totalHits: 命中数, 数组的长度,后面用来做分页 * ScoreDoc[]: 存储匹配的文档编号的数组 * Score: 文档的积分,按照命中率自动算出来 * Doc:当前文档的编号 */ //增加排序的效果 /*对象查询的结果进行排序: Lucene排序有两种: 命中率排序, 根据字段排序 *注意 这两种排序方式不互斥的,如果选择按字段排序命中率是不会被计算出来, 但是字段排序本身可以支持多字段 *被排序的字段,和被删除更新一样 字段必须创建索引 * true代表的是降序 */ Sort sort=new Sort(new SortField("id",SortField.INT, true),new SortField("price", SortField.DOUBLE,true)); TopDocs topDocs= searcher.search(query, null, 5, sort); // 此变量/每页显示的记录数就是总页数 System.out.println("真正命中的结果数:" + topDocs.totalHits); // 返回的是符合条件的文档编号,并不是文档本事 ScoreDoc scoreDocs[]= topDocs.scoreDocs; for(int i=0;i<scoreDocs.length;i++){ ScoreDoc scoreDoc= scoreDocs[i]; System.out.println("真正的命中率:"+scoreDoc.score); System.out.println("存储的是文档编号:"+scoreDoc.doc); Document doc= searcher.doc(scoreDoc.doc); System.out.println(doc.get("id")); System.out.println(doc.get("name")); System.out.println(doc.get("price")); System.out.println(doc.get("remark")); System.out.println("---------"); // Goods goods=new Goods(); // goods.setId(Integer.parseInt(doc.get("id"))); // goods.setName(doc.get("name")); // goods.setPrice(Double.parseDouble(doc.get("price"))); // goods.setRemark(doc.get("remark")); doc.getField("name").setValue(HighlighterUtil.setHighlighterText(query, doc.get("name"), 10)); doc.getField("remark").setValue(HighlighterUtil.setHighlighterText(query, doc.get("remark"), 15)); goodsList.add(DocumentUtil.documentToGoods(doc)); } } catch (Exception e) { // TODO Auto-generated catch block throw new RuntimeException(e); } return goodsList; }
测试类:
@Test public void testquery() { List<Goods> list= hellowod.queryGoods("ibm"); for(Goods good:list){ System.out.println("商品编号:"+good.getId()+",商品名称:"+good.getName()+ ",商品价格:"+good.getPrice()+",商品的详细信息:"+good.getRemark() ); } }
查询的结果:
商品编号:12,商品名称:<font color='red'>IBM</font>,商品价格:4333.9,商品的详细信息:<font color='red'>IBM</font> Computer 商品编号:11,商品名称:<font color='red'>IBM</font>,商品价格:3333.9,商品的详细信息:<font color='red'>IBM</font> Computer 商品编号:11,商品名称:<font color='red'>IBM</font>是全球知名的,商品价格:2333.9,商品的详细信息:<font color='red'>IBM</font>有质量保证,耐用
我们可以发现高亮的html代码包裹着关键字。
相关文章推荐
- JAVAWEB开发之Lucene详解——Lucene入门及使用场景、全文检索、索引CRUD、优化索引库、分词器、高亮、相关度排序、各种查询
- Lucene 3.6.1:中文分词、创建索引库、排序、多字段分页查询以及高亮显示
- JAVA_WEB项目之Lucene检索框架实现增删查改的代码优化以及分页功能实现
- lucene中处理将查询结果中的关键字高亮显示
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(七) 之 历史记录查询(时间,关键字,图片,文件),关键字高亮显示。
- lucene实现 某段时间内 多个存储字段 多关键字的查询 并且加入排序规则 思路
- LuceneSearch 现在要对查询结果进行排序的显示。
- asp.net中利用Lucene.net实现检索并对检索关键字高亮显示
- 利用Lucene.net实现检索并对检索关键字高亮显示
- 用java把从数据库中查询出的结果集重新按照结果中的几个字段重新排序
- 使用Lucene的highlight包高亮显示检索关键字
- [ lucene FAQ ] 检索结果怎么排序?对于不同类型(例如int型)的字段排序有什么区别吗?
- java socket编程,客户端发出检索字段,服务端查询数据并返回结果集
- 实现在搜索后将结果中的关键字高亮显示
- JAVA_WEB项目之使用Spring的xml配置方式在项目中管理Lucene检索框架
- 使用lucene将索引结果进行高亮显示
- 项目____DUPLICATE、int/varchar、根据多字段排序、根据查询结果反查
- Lucene 对搜索关键字进行高亮显示
- 实现lucene检索结果排序
- android+lucene实现全文检索并高亮关键字