用Lucene实现分组,facet功能,FieldCache
假如你像用lucene来作分组,比如按类别分组,这种功能,好了你压力大了,lucene本身是不支持分组的。
当你想要这个功能的时候,就可能会用到基于lucene的搜索引擎solr。
不过也可以通过编码通过FieldCache和单字段,对索引进行分组,比如:想构造类别树。大类里面还有小类那种。
这个功能实现起来可能会比较麻烦,主要是lucene提供的支持也不多,参考资料也不多。
(以下代码都是我在做测试的时候做的,可以稍作修改满足相应需求。)
//用于分组统计的对象GroupCollector
import java.io.IOException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Scorer;
public class GroupCollector extends Collector {
private GroupField gf = new GroupField();// 保存分组统计结果
private int docBase;
// fieldCache
private String[] fc;
@Override
public boolean acceptsDocsOutOfOrder() {
return true;
}
@Override
public void collect(int doc) throws IOException {
// 因为doc是每个segment的文档编号,需要加上docBase才是总的文档编号
final int docId = doc + this.docBase;
// 添加的GroupField中,由GroupField负责统计每个不同值的数目
this.gf.addValue(this.fc[docId]);
}
@Override
public void setNextReader(IndexReader arg0, int arg1) throws IOException {
this.docBase = this.docBase;
}
@Override
public void setScorer(Scorer arg0) throws IOException {
}
public GroupField getGf() {
return this.gf;
}
public void setGf(GroupField gf) {
this.gf = gf;
}
public int getDocBase() {
return this.docBase;
}
public void setDocBase(int docBase) {
this.docBase = docBase;
}
public String[] getFc() {
return this.fc;
}
public void setFc(String[] fc) {
this.fc = fc;
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 用于保存分组统计后每个字段的分组结果
*/
public class GroupField {
/**
* 字段名
*/
private String name;
/**
* 商品类型的对象列表
*/
private List<SimpleCategory> values = new ArrayList<SimpleCategory>();
/**
* 保存字段值和文档个数的对应关系
*/
private Map<String, Integer> countMap = new HashMap<String, Integer>();
public Map<String, Integer> getCountMap() {
return this.countMap;
}
public void setCountMap(Map<String, Integer> countMap) {
this.countMap = countMap;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public List<SimpleCategory> getValues() {
return this.values;
}
public void setValues(List<SimpleCategory> values) {
this.values = values;
}
/**
* 用于商品对象list的构造
*
* @param value
*/
public void addValue(String value) {
if ((value == null) || "".equals(value)) return;
// 对于多值的字段,支持按空格拆分
final String[] temp = value.split(",");
if (this.countMap.get(temp[1]) == null) {
this.countMap.put(temp[1], 1);
// 构造商品类型临时对象
final SimpleCategory simpleCategory = new SimpleCategory();
simpleCategory.setCategoryId(Integer.parseInt(temp[0]));
simpleCategory.setCategoryName(temp[1]);
simpleCategory.setParentId(Integer.parseInt(temp[2]));
simpleCategory.setSortIndex(temp[3]);
simpleCategory.setParentCategoryName(temp[4]);
// simpleCategory.setAdImag(temp[5]);
// simpleCategory.setParentAdImage(temp[6]);
this.values.add(simpleCategory);
}
else {
this.countMap.put(temp[1], this.countMap.get(temp[1]) + 1);
}
// for( String str : temp ){
// if(countMap.get(str)==null){
// countMap.put(str,1);
// values.add(str);
// }
// else{
// countMap.put(str, countMap.get(str)+1);
// }
// }
}
// class ValueComparator implements Comparator<String>{
//
// // public int compare(String value0, String value1) {
// // if(countMap.get(value0)>countMap.get(value1)){
// // return -1;
// // }
// // else if(countMap.get(value0)<countMap.get(value1)){
// // return 1;
// // }
// // return 0;
// // }
// }
}
自己构建想返回的对象
/**
* 用于将lucene索引中的商品类型CategoryIndex字段,转换成商品类型的一个对象。
*
* @author xiaozd
*
*/
public class SimpleCategory extends BaseModel {
private static final long serialVersionUID = -2345212345526771266L;
private int parentId;
private int categoryId;
private String categoryName;
private String sortIndex;
private int goodsCount;
private String parentCategoryName;
public int getParentId() {
return this.parentId;
}
public void setParentId(int parentId) {
this.parentId = parentId;
}
public int getCategoryId() {
return this.categoryId;
}
public void setCategoryId(int categoryId) {
this.categoryId = categoryId;
}
public String getCategoryName() {
return this.categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getSortIndex() {
return this.sortIndex;
}
public void setSortIndex(String sortIndex) {
this.sortIndex = sortIndex;
}
public static long getSerialversionuid() {
return SimpleCategory.serialVersionUID;
}
public int getGoodsCount() {
return this.goodsCount;
}
public void setGoodsCount(int goodsCount) {
this.goodsCount = goodsCount;
}
public String getParentCategoryName() {
return this.parentCategoryName;
}
public void setParentCategoryName(String parentCategoryName) {
this.parentCategoryName = parentCategoryName;
}
}
/**
* 查询商品的所有类型,方式:通过索引分组查询所有类型。
* @return Map<String, String> 第一个参数表示商品类型id,第二个String表示商品类型名称
*/
public List<SimpleCategory> getGoodsCategory() {
List<SimpleCategory> values=new ArrayList<SimpleCategory>();
try {
IndexReader reader = IndexReader.open(FSDirectory.open(new File(luceneSearchPath)), true); // only searching, so read-only=true
//读取"modified"字段值,放到fieldCache中
final String[] fc=FieldCache.DEFAULT.getStrings(reader, "categoryIndex");
IndexSearcher searcher = new IndexSearcher(reader);
//GroupCollector是自定义文档收集器,用于实现分组统计
GroupCollector myCollector=new GroupCollector();
myCollector.setFc(fc);
searcher.search(new MatchAllDocsQuery(), myCollector);
//GroupField用来保存分组统计的结果
GroupField gf=myCollector.getGf();
values=gf.getValues();
for (SimpleCategory value : values) {
System.out.println("商品类型名称: "+value +" 数量:"+gf.getCountMap().get(value.getCategoryName())+" 商品父类型名称: "+value.getParentCategoryName());
}
} catch (Exception e) {
e.printStackTrace();
}
return values;
}
http://blog.csdn.net/xiaozhengdong/article/details/7035607
用Lucene实现分组,facet功能,FieldCache的更多相关文章
- lucene搜索之facet查询原理和facet查询实例——TODO
转自:http://www.lai18.com/content/7084969.html Facet说明 我们在浏览网站的时候,经常会遇到按某一类条件查询的情况,这种情况尤以电商网站最多,以天猫商城为 ...
- MYSQL-实现ORACLE- row_number() over(partition by ) 分组排序功能
MYSQL-实现ORACLE- row_number() over(partition by ) 分组排序功能 由于MYSQL没有提供类似ORACLE中OVER()这样丰富的分析函数. 所以在MYSQ ...
- SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表
SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表 SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表 2013-10-09 23:09 by BI Wor ...
- Lucene最重要的功能是对一段话的分析
Lucene最重要的功能是对一段话的分析
- MYSQL-实现分组排序 对比 ORACLE 和SQLserver用 row_number() over(partition by ) 分组排序功能
以下是个人笔记: 本文是为了理解 row_number() over(partition by ) 和实现各种数据库的分组排序功能 select ROW_NUMBER()over( partitio ...
- 相似group by的分组计数功能
之前同事发过一个语句,实现的功能比較简单,相似group by的分组计数功能,由于where条件有like,又无法用group by来实现. SELECT a.N0,b.N1,c.N2,d.N3,e. ...
- 使用Lucene.NET实现数据检索功能
引言 在软件系统中查询数据是再平常不过的事情了,那当数据量非常大,数据存储的媒介不是数据库,或者检索方式要求更为灵活的时候,我们该如何实现数据的检索呢?为数据建立索引吧,利用索引技术可以更灵活 ...
- FastScroll(2)不分组的listview 打开fastscroll的分组提示功能
本文只让fastscroll具有提示分组功能,但listview并不显示分组,如果想让分组的listview显示fastscroll,看下篇. 1,在listview中打开fastscroll 2,自 ...
- BuguMongo是一个MongoDB Java开发框架,集成了DAO、Query、Lucene、GridFS等功能
http://code.google.com/p/bugumongo/ 简介 BuguMongo是一个MongoDB Java开发框架,它的主要功能包括: 基于注解的对象-文档映射(Object-Do ...
随机推荐
- python-条件和循环
条件 Demo1: if i < 10: print('i<10') elif i == 0: print('i=0 ') else: print('...') Demo1说明了以下几点: ...
- mysql与redis的区别与联系
1.mysql是关系型数据库,主要用于存放持久化数据,将数据存储在硬盘中,读取速度较慢. redis是NOSQL,即非关系型数据库,也是缓存数据库,即将数据存储在缓存中,缓存的读取速度快,能够大大的提 ...
- 注册google账号 解决国内手机注册失败的问题
1. PC端下载夜神安卓模拟器.安装,启动. 2. 在模拟器里的市场应用里下载qq邮箱. 3. 启动邮箱,选择gmail,注册.后续一切顺利. 这是迄今为止,唯一注册顺利的方法.其他方法,手机验证一关 ...
- Python issubclass() 函数
Python issubclass() 函数 Python 内置函数 描述 issubclass() 方法用于判断参数 class 是否是类型参数 classinfo 的子类. 语法 以下是 iss ...
- iOS 代码调试
僵尸对象导致crash(Thread 1:EXC_BAD_ACCESS(code=EXC_I386_GPFLT)),需要给位release模式,debug模式不打印内存地址 https://blog. ...
- OC线程操作-GCD介绍
1. GCD介绍 1.11.2 1.3 异步具备开启能力但是不是 一定可以开启 1.4 1.5 67. 8.
- Linux 下 FastDFS v5.08 分布式文件系统的安装
一.系统安装目录 源代码包目录 /data/wwwroot libevent安装目录 /usr/local/libevent FastDFS安装目录 /data/fastdfs nginx安装目录 / ...
- PHP下ajax跨子域的解决方案之document.domain+iframe
对于主域相同,子域不同,我们可以设置相同的document.domain来欺骗浏览器,达到跨子域的效果. 例如:我们有两个域名:www.a.com 和 img.a.com 在www.a.com下有 ...
- linux下安装php php-fpm(转载)
centos安装php php-fpm 1.下载php源码包http://www.php.net/downloads.php2 .安装phptar -xvf php-5.5.13.tar.bz2cd ...
- SQL思维导图