solr高级使用之group和facet

Group对比Facet

Group和Facet的概念很像,都是用来分组。Facet返回所有相关的结果并允许用户基于facet的目录重新定义结果集。Facet可以对分组数量进行过滤,以及排序,和日期范围,时间范围分组,但是如果你想得到具体的数据,还得需要查询一次或多次。group可以得到分组的组数量,一次请求,可以拿到所有的数据。 
Group和Facet可以结合起来使用,但只能使用facet.fieldfacet.range,还不支持日期date和维度统计pivot faceting.

Group参数

参数 类型 说明
group 布尔值 设为true,表示结果需要分组
group.field 字符串 需要分组的字段,字段类型需要时是StrField或TextField
group.func 查询语句 可以指定查询函数
group.query 查询语句 可以指定查询语句
rows 整数 返回多少组结果,默认10
start 整数 指定结果开始位置/偏移量
group.limit 整数 每组返回多数条结果,默认1
group.offset 整数 指定每组结果开始位置/偏移量
sort 排序算法 控制各个组的返回顺序
group.sort 排序算法 控制每一分组内部的顺序
group.format grouped/simple 设置为simple可以使得结果以单一列表形式返回
group.main 布尔值 设为true时,结果将主要由第一个字段的分组命令决定
group.ngroups 布尔值 设为true时,Solr将返回分组数量,默认fasle
group.truncate 布尔值 设为true时,facet数量将基于group分组中匹相关性高的文档,默认fasle
group.cache.percent 整数0-100 设为大于0时,表示缓存结果,默认为0。该项对于布尔查询,通配符查询,模糊查询有改善,却会减慢普通词查询。
public void SearchGroup(String QUERY_CONTENT,int QUERY_ROWS, Boolean GROUP, String GROUP_FIELD,String GROUP_LIMIT) {
         SolrServer server = createSolrServer();  
         SolrQuery param = new SolrQuery();  
         param.setQuery("jobsName:"+QUERY_CONTENT);  
         param.setRows(QUERY_ROWS);  
         param.setParam(GroupParams.GROUP, GROUP);  
         param.setParam(GroupParams.GROUP_FIELD, GROUP_FIELD);          
         param.setParam(GroupParams.GROUP_LIMIT, GROUP_LIMIT);  
         QueryResponse response = null;  
         try {  
             response = server.query(param);  
         } catch (SolrServerException e) {  
            // logger.error(e.getMessage(), e);  
         }  
         Map info = new HashMap();  
         GroupResponse groupResponse = response.getGroupResponse();  
         if(groupResponse != null) {  
             List groupList = groupResponse.getValues();  
             for(GroupCommand groupCommand : groupList) {  
                 List groups = groupCommand.getValues();  
                 for(Group group : groups) {  
                     info.put(group.getGroupValue(), (int)group.getResult().getNumFound()); 
                     System.out.println(group.getGroupValue()+"---"+group.getResult().getNumFound());
                 }  
             }  
         }  
    }

一、Group用法:

//组查询基础配置
params.set(GroupParams.GROUP, "true"); 
params.set(GroupParams.GROUP_FIELD, "dkeys");根据dkeys域上的值来分组划分结果,建议dkeys上不要分词;
params.set(GroupParams.GROUP_LIMIT, "5"); 
params.set(GroupParams.GROUP_FORMAT, "grouped"); 
params.set(GroupParams.GROUP_MAIN, "false"); 

Group查询结果遍历方式:

QueryResponse response = solrServer.query(query);
GroupResponse groupResponse = response.getGroupResponse();  
List ls = groupResponse.getValues();
for(GroupCommand gc:ls){
    List list = gc.getValues();
    for(Group g : list){
        SolrDocumentList sdl = g.getResult();
        if (CollectionUtils.isNotEmpty(sdl)) {  
             for (SolrDocument doc : sdl) {  
                 System.out.println(doc.toString());//相同的dkeys下的文档每5个作为一组返回;
             }
        }
    }
}

此时普通遍历结果的方法无效:

SolrDocumentList results = response.getResults(); 
System.out.println(ls+"\t\t"+results);//输出null

facet使用:

参数 描述
facet 为TRUEON时,启用该功能
facet.query

默认情况下,Solr会自动Facet的field并返回其相关的计数结果 。指定Lucene语法的查询语句,可以覆盖默认行为。可以设置多个

日期区间查询:

facet.query=date:[2009-1-1T0:0:0Z TO 2009-2-1T0:0:0Z]

数字区间统计;

facet.query=price:[5000 TO 10000]

facet.field 指定作为facet的field。比如“品牌”,可以设置多个
facet.prefix 以此值为前辍的terms才会作为Facet
facet.contains 字符串包含此值的terms才会作为Facet
facet.contains.ignoreCase 匹配 facet.contains 条件时,忽略大小写
facet.sort 指示Facet结果如何排序。有两个值:1. count -- facet记录数多的排前面 2. index -- 按索引中的次序
facet.limit 限制返回的facet的数量。默认100. 为负数时表示不做限制。e.g. 设置为2的话,只返回品牌、类型和颜色中的2种。
facet.offset 默认0. 一般用于分页时,忽略前面多少个
facet.minCount 设置最小的数量。限制了Facet字段值的最小count,默认为0.合理设置该参数可以将用户的关注点集中在少数比较热门的领域.相当于group by having
facet.missing 默认值false. 如果设置为true或者on,那么将统计那些该Facet字段值为null的记录
facet.method facet的算法。三个可选值:enum, fc(默认值),fcs;enum适用于字段值比较少的情况,比如字段类型为布尔型,或者字段表示中国的所有省份
facet.exists 用于facet.method=enum的情况
facet.excludeTerms 排除某些terms
facet.threads 获得facet的计算的线程数
facet.date 该参数表示需要进行Date Facet的字段名,与facet.field一样,该参数可以被设置多次,表示对多个字段进行Date Facet
facet.date.start 起始时间
facet.date.end 结束时间
facet.date.gap

时间间隔.如果start为2009-1-1,end为2010-1-1.gap设置为+1MONTH表示间隔1个月,那么将会把这段时间划分为12个间隔段。注意+因为是特殊字符所以应该用%2B代替

facet.date.hardend

取值可以为true|false,默认为false.它表示gap迭代到end处采用何种处理.举例说明start为2009-1-1,end为2009-12-25,gap为+1MONTH;

hardend为false的话最后一个时间段为2009-12-1至2010-1-1;

hardend为true的话最后一个时间段为2009-12-1至2009-12-25

facet.date.other 取值范围为before|after|between|none|all,默认为none,before会对start之前的值做统计,after会对end之后的值做统计,between会对start至end之间所有值做统计.如果hardend为true的话,那么该值就是各个时间段统计值的和.none表示该项禁用.all表示before,after,all都会统计
facet.range 范围统计分组统计,跟Date Facet一样,只是他们定位的字段的类型不同,Data Fact是做日期的分组统计的,而Fact Range是做数字分组统计的,在次强调,是做数字分组统计的,对于字符串,日期是不可以的

facet.range.start

 
facet.range.end  
facet.range.gap  
facet.range.hardend  
facet.range.other  
facet.range.include  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

public JiucaiyunSolrResponseDTO queryData(JiucaiyunSolrRequestDTO request) throws JiucaiyunSolrException {
		try {

			// int index = 5/0;
			// 索引条件
			SolrQuery params = new SolrQuery();
			params.setQuery(request.getkeywords());
			String keyWord = "*";
			if (request.getkeywords() != null && !"".equals(request.getkeywords().trim())) {
				keyWord = request.getkeywords().trim();
			}
			params.set("q", "keywords:" + keyWord);
			if (null != request.getcatalog() && !"".equals(request.getcatalog().trim())) {
				params.add("fq", "catalog:" + request.getcatalog().trim());
			}
			String brand2 = request.getbrand();
			if (null != brand2 && !"".equals(brand2.trim())) {
				if (brand2.contains(" ")) {
					brand2 = brand2.trim().replace(" ", "\\ ");
				}
				// brand2 = SolrUtils.transformSolrMetacharactor(brand2);
				params.add("fq", "brand:" + brand2);
			}
			if (null != request.getprice()) {
				String[] price = request.getprice().split("-");
				if (price.length == 2) {
					params.add("fq", "price:[" + price[0] + " TO " + price[1] + "]");
				} else {
					params.add("fq", "price:[" + price[0] + " TO *]");
				}
			}
			String model2 = request.getmodel();
			if (null != model2 && !"".equals(model2.trim())) {
				if (model2.contains(" ")) {
					model2 = model2.trim().replace(" ", "\\ ");
				}
				// brand2 = SolrUtils.transformSolrMetacharactor(brand2);
				params.add("fq", "model:" + model2);
			}
			if (null != request.gettype() && !"".equals(request.gettype().trim())) {
				params.add("fq", "type:" + request.gettype().trim());
			}
			if (null != request.getsupplierid() && !"".equals(request.getsupplierid().trim())) {
				String[] strs = request.getsupplierid().split(",");
				if (strs.length > 1) {
					String per = "";
					for (int i = 0; i < strs.length; i++) {
						if (i == 0) {
							per = per + " supplierid:" + strs[i];
						} else {
							per = per + " OR supplierid:" + strs[i];
						}
					}
					params.add("fq", per);
				} else {
					params.add("fq", "supplierid:" + request.getsupplierid().trim());
				}
			}
			if (null != request.getsuppliernum() && !"".equals(request.getsuppliernum().trim())) {
				params.add("fq", "suppliernum:" + request.getsuppliernum().trim());
			}
			if (null != request.getpermission() && !"".equals(request.getpermission().trim())) {
				String[] pers = request.getpermission().trim().split(",");
				String per = "permission:\"\"";
				for (String str : pers) {
					per = per + " OR permission:" + str;
				}
				params.add("fq", per);
			}
			// 1:打开高亮的开关
			if (null != request.getkeywords() && !"".equals(request.getkeywords().trim())) {
				params.setHighlight(true);
				// 2:设置需要高亮的域
				params.addHighlightField("supplier_name");
				params.addHighlightField("name");
				// 3:高亮的前缀 后缀
				params.setHighlightSimplePre("");
				params.setHighlightSimplePost("");
			}
			// 分页
			params.setStart(request.getStartRow());
			params.setRows(request.getPageSize());
			// 排序
			if ("asc".equals(request.getprice_order()) && (null == request.getsalesvolume_order()
					|| "".equals(request.getsalesvolume_order().trim()))) {
				params.setSort("price", ORDER.asc);
			} else if ("desc".equals(request.getprice_order())
					&& (null == request.getsalesvolume_order()
							|| "".equals(request.getsalesvolume_order().trim()))) {
				params.setSort("price", ORDER.desc);
			}
			if (null != request.getsalesvolume_order() && (null == request.getprice_order()
					|| "".equals(request.getprice_order().trim()))) {
				params.setSort("salesvolume", ORDER.desc);
			}
			params.set("wt", "json");
			params.set("facet", true);
			params.add("facet.field", "catalog_name");
			params.add("facet.field", "brand");
			params.add("facet.field", "model");
			params.add("facet.field", "type");
			QueryResponse query = solrClient.query(params);

			List facetFields = query.getFacetFields();
			List category = new ArrayList();
			List brands = new ArrayList();
			List type = new ArrayList();
			List models = new ArrayList();

			for (FacetField ff : facetFields) {
				String name = ff.getName();
				switch (name) {
				case "catalog_name":
					List cate = ff.getValues();
					for (Count c : cate) {
						if (c.getCount() > 0) {
							String[] strs = c.getName().split(",");
							category.add(new JiucaiyunSolrCategoryDTO(strs[0], strs[1]));
						}
					}

					break;
				case "brand":
					List brand = ff.getValues();
					for (Count c : brand) {
						if (c.getCount() > 0) {
							brands.add(new JiucaiyunSolrBrandDTO(c.getName()));
						}
					}
					break;
				case "type":
					List t = ff.getValues();
					for (Count c : t) {
						if (c.getCount() > 0) {
							type.add(new JiucaiyunSolrTypeDTO(c.getName()));
						}
					}
					break;
				case "model":
					List model = ff.getValues();
					for (Count c : model) {
						if (c.getCount() > 0) {
							models.add(new JiucaiyunSolrModelDTO(c.getName()));
						}
					}
					break;

				default:
					break;
				}
			}
			SolrDocumentList results = query.getResults();
			// 获取高亮
			Map>> highlighting = query.getHighlighting();
			// 1: Map K id V : map
			// 2: Map K name_ik V list
			// 3: list apache 不一个 多值 本次只有一个值 list.get(0)
			// 总条数
			long numFound = results.getNumFound();
			List goodsList = new ArrayList();

			for (SolrDocument doc : results) {
				JiucaiyunSolrProductDTO product = new JiucaiyunSolrProductDTO();
				// 商品ID
				String id = (String) doc.get("id");
				product.setId(id);
				Map> map = new HashMap>();
				if (null != highlighting) {
					map = highlighting.get(id);
				}

				// 商品名称
				if (null != map && null != map.get("name")) {
					product.setName(map.get("name").get(0));
				} else {
					product.setName((String) doc.get("name"));
				}
				product.setName1((String) doc.get("name"));
				// 供应商名称
				if (null != map && null != map.get("supplier_name")) {
					product.setSupplier(map.get("supplier_name").get(0));
				} else {
					product.setSupplier((String) doc.get("supplier_name"));
				}
				product.setSupplier1((String) doc.get("supplier_name"));
				// 供应商编码
				product.setSuppliernum((String) doc.get("suppliernum"));
				// 供应商id
				product.setSupplierid((String) doc.get("supplierid"));
				// wareId
				product.setWareid((String) doc.get("wareid"));
				// 商品sku
				product.setGoodsnum((String) doc.get("num"));
				// 商品品牌
				product.setBrand((String) doc.get("brand"));
				// 规格
				product.setModel((String) doc.get("model"));
				// 商品url
				product.setUrl((String) doc.get("picture"));
				// 商品imgid
				product.setImgid((String) doc.get("pictureid"));
				// 商品价格
				product.setPrice(String.valueOf(doc.get("price")));
				// 商品有效期
				product.setSuccessdate((String) doc.get("successdate"));
				// 商品销量
				product.setSalesvolume((String) doc.get("salesvolume"));
				// 起购量
				product.setMinimumquantity((String) doc.get("minimum_quantity"));
				if (null != request.getlevel() && !"".equals(request.getlevel())) {
					Integer goodsid = null;
					if (this.isNumeric(product.getId())) {
						goodsid = Integer.valueOf(product.getId());
						BigDecimal levelPrice = jiucaiyunSolrDao.getLevelPrice(goodsid, request.getlevel());
						if (null != levelPrice) {
							product.setPrice(levelPrice + "");
						}
					}
				}
				goodsList.add(product);
			}

			JiucaiyunSolrResponseDTO response = new JiucaiyunSolrResponseDTO();
			response.setGoodsList(goodsList);
			response.setBrands(brands);
			response.setCategory(category);
			response.setType(type);
			response.setModels(models);
			response.setTotalnum(numFound);
			if (null != request.getsupplierid() && !"".equals(request.getsupplierid().trim())) {
				String[] strs = request.getsupplierid().split(",");
				List suppliers = new ArrayList<>();
				for (String str : strs) {
					int supplierid = Integer.parseInt(str);
					JiucaiyunSolrSupplierDTO supplier = querySupplier(supplierid);
					suppliers.add(supplier);
				}
				response.setSuppliers(suppliers);
				response.setSupplier(suppliers.get(0));
			}
			return response;
		} catch (Exception e) {
			// logger.error(e.getMessage(),e);
			e.printStackTrace();
			return null;
		}
	}

 

你可能感兴趣的:(高级搜索和日志)