我是靠谱客的博主 寒冷导师,最近开发中收集的这篇文章主要介绍Solr---Facet分面查询,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

场景描述:

      Solr具有分面查询的功能,其中包含字段分面、间隔分面、区间分面。网上讲的都是字段分面,区间分面少之又少,而且通过solrj从java查询的文章也少的可怜,所以在这里,讲一下我是如何操作的。

设置分面参数:

// 创建solrQuery对象
SolrQuery query = new SolrQuery();
...
//设置分面
query.setFacet(true); // 设置使用facet
query.setFacetMinCount(1); // 设置facet最少的统计数量
query.setFacetLimit(10); // facet结果的返回行数

字段分面:

/*字段分面*/
query.addFacetField("FILE_TYPE"); // facet的字段 文档类型
query.addFacetField("DISEASE_TYPE"); // facet的字段 疾病
query.addFacetField("DEPT_NAME"); // facet的字段 科室
query.addFacetField("SEX"); // facet的字段 性别
...
// 执行搜索,返回response对象
QueryResponse rq = cloudSolrClient.query(query);
/*字段分面*/
List<FacetField> flist=rq.getFacetFields();
// 格式为:{分面字段:{字段内容:计数}...},比如{SEX:{"男":17,"女":15},DEPT_NAME:{...}...}
JSONObject facetJson = new JSONObject();
// 格式为:{字段内容:计数},比如{"男":17}
JSONObject facetContentJson = new JSONObject();
for(FacetField ff : flist) {
    // 每次清空之前的内容
    facetContentJson.clear();
    // 这里采用全名,是为了避免与其他分面的变量名同为Count的问题
    for(org.apache.solr.client.solrj.response.FacetField.Count c:ff.getValues()) {
        facetContentJson.put(c.getName(), c.getCount());
    }
    facetJson.accumulate(ff.getName(), facetContentJson );   
}

间隔分面:

/*间隔分面*/
query.addIntervalFacets("AGE",new String[]{"[0,1]","(1,14]","[15,35]","(35,60]","(60,*]"});
/* 间隔分面*/
//年龄间隔分面
for (IntervalFacet intervalFacet:rq.getIntervalFacets()){
    // 清空之前数据
    facetContentJson.clear();
for( IntervalFacet.Count c:intervalFacet.getIntervals()) {
//区间分面内容【0-1】,(1,14】,【15,35】,(35,60】,(60,*】
switch (i){
case 0:
if (c.getCount()==0){
break;
}else{
facetContentJson.put("0-1岁", c.getCount());
break;
}
case 1:
if (c.getCount()==0){
break;
}else{
facetContentJson.put("1-14岁", c.getCount());
break;
}
case 2:
if (c.getCount()==0){
break;
}else{
facetContentJson.put("15-35岁", c.getCount());
break;
}
case 3:
if (c.getCount()==0){
break;
}else{
facetContentJson.put("35-60岁", c.getCount());
break;
}
case 4:
if (c.getCount()==0){
break;
}else{
facetContentJson.put("60岁以上", c.getCount());
break;
}
default:
break;
}
}
    facetJson.accumulate(intervalFacet.getField(), facetContentJson);
}

时间区间分面:

/*时间区间分面*/
// 2010-今年
// 时间对象
Calendar cal = Calendar.getInstance();
// 设置当前时间为加8小时,因为时区的问题,在处理之后发送查询条件中是减过8小时的所以这里,加上8小时
cal.add(Calendar.HOUR,+8);
// java时间格式
SimpleDateFormat ymdhmsSdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 设置solr时间格式
SimpleDateFormat solrSdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
// 按月分
query.addDateRangeFacet("CREATE_TIME", ymdhmsSdf.parse("2010-01-01 08:00:00"),cal.getTime() , "+1MONTH");
/* 时间区间分面*/
@SuppressWarnings("rawtypes")
List<RangeFacet> rlist=rq.getFacetRanges();
if(rlist!=null&&rlist.size()>0){
for(int i=0;i<rlist.size();i++) {
List<org.apache.solr.client.solrj.response.RangeFacet.Count> clist=rlist.get(i).getCounts();
// 清空之前数据
facetContentJson.clear();
// 将月份与月份对应的结果放入的分面json中
for(int j=clist.size()-1;j>=0;j--) {
facetContentJson.put(ymSdf.format(solrSdf.parse(clist.get(j).getValue())), clist.get(j).getCount());
}
facetJson.accumulate(rlist.get(i).getName(), facetContentJson);
}
}

        该方法(addDateRangeFacet)是针对时间的,其中作为时间区间分面的字段在Solr配置文件中需要设置为时间格式,还有一个方法是针对数字区间的(addNumericRangeFacet)。其中时间区间的方法最后一个参数是时间间隔“gap”为字符串属性,内容为”+1YEAR”,”+1MONTHS”,”+1DAY”,”+1HOUR”。

总结:

    结果的结构里都有Count类型数据,但是字段分面的是FacetField.Count,区间分面的是RangeFacet.Count,所以在遍历Count属性的List时候,我是将整个包名放在上面,如果你只用到两种分面中的一种,则不需要这样写,只导入你用的那个包就够了。其中可以注意到,从Solr里获取到的时间格式为:"yyyy-MM-dd'T'HH:mm:ss'Z'",这个是Solr固定的时间格式。

注意事项:

1.在后续时间处理诸如,query.addFilterQuery(entry.getKey()+":["+solrSdf.format(sdf.parse((String) entry.getValue()))+" TO NOW]");这样的时间处理时,格式需要特别注意,“TO”两边的空格也不能漏掉。“]”代表包含,“}”代表不包含;

2.时间区间的查询时间范围,因为时区的问题,增加了8小时;原因请参考我的这一篇

3.java中的时间格式“YYYY”与“yyyy”是两种概念也需要注意,不能写错了。



最后

以上就是寒冷导师为你收集整理的Solr---Facet分面查询的全部内容,希望文章能够帮你解决Solr---Facet分面查询所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部