场景描述:
Solr具有分面查询的功能,其中包含字段分面、间隔分面、区间分面。网上讲的都是字段分面,区间分面少之又少,而且通过solrj从java查询的文章也少的可怜,所以在这里,讲一下我是如何操作的。
设置分面参数:
1
2
3
4
5
6
7// 创建solrQuery对象 SolrQuery query = new SolrQuery(); ... //设置分面 query.setFacet(true); // 设置使用facet query.setFacetMinCount(1); // 设置facet最少的统计数量 query.setFacetLimit(10); // facet结果的返回行数
字段分面:
1
2
3
4
5
6
7
8
9/*字段分面*/ 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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/*字段分面*/ 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 ); }
间隔分面:
1
2
3/*间隔分面*/ query.addIntervalFacets("AGE",new String[]{"[0,1]","(1,14]","[15,35]","(35,60]","(60,*]"});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49/* 间隔分面*/ //年龄间隔分面 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); }
时间区间分面:
1
2
3
4
5
6
7
8
9
10
11
12
13/*时间区间分面*/ // 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");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/* 时间区间分面*/ @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分面查询内容请搜索靠谱客的其他文章。
发表评论 取消回复