电商搜索之动态属性值(特征值)聚合

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hu948162999/article/details/49280071

转载请标明出处:http://blog.csdn.net/hu948162999/article/details/49280071

在一些电商网站中,有部分这样的搜索需求:

 1:根据关键字搜索商品,要制作商品属性值(也称特征值,导航栏),但是这个商品属性值(也称特征值,导航栏)是动态的。

 2:关键字是和台式机有关的,那么属性值要有CPU型号,显卡型号等等参数选择。

 3:关键字是和服装相关的,那么属性值要有款式,尺码,等等参数选择。

 4:有些公共的属性,比如品牌、价位、类别、大家说。

 类似京东:



在solr中,用facet 可以实现以上属性值聚合的需求,facet的基本功能就是对搜索结果中的商品的共有属性进行聚合统计。facet功能很强大,具体本文就不相信列出了。

 但是非公共属性值的话,solr要求facet 必须要指定聚合字段,没有字段是完不了facet操作的。

如何完成以上需求?

当初一共思考了两种方案:


一:这一种方案可行性挺高,由于我没有采用该方案,但是这种方式我认为 是可以实现的。

 把所有的商品的动态(非共性)的属性值建立索引的时候,全部以特殊符号形成的格式加入某个指定字段,如:key:value,key:value......用这个数据格式去存储商品的

所有属性值。   然后用自定义的分词器(通过“:” “,” 的切词规则)切开这些属性值,然后在进行该字段的facet聚合。

 

二:在我的实际应用中,我采用的是这种方案,具体实现:

 在solr中,有一种字段是动态的,dynamicField。指定所有非公共属性特征值字段存储格式为:

<dynamicField name="*_proper" type="string" indexed="true" stored="true"/><!-- 动态string字段 -->

注:用于facet的字段的索引index一定要设为true,不要分词,默认使用string类型。


这样还有那个问题,我们还是不知道具体应该facet的字段是哪一个。

那么,分两次查询。

第一次查询所有非公共属性名称(key)。

<field name="proper" type="string" indexed="true" stored="true"  multiValued="true"/> 

用这一个在第一次查询的时候就可以确定,返回结果中有哪些属性值字段应该被facet聚合。


第二次查询就可以指定以上字段:key_proper 字段作为facet字段。

附上业务代码:

		/**
		 * 特征值聚合
		 * 先获取结果集文档中的特征属性
		 * 对特征属性进行二次聚合  域:  属性+_string 进行第二次查询
		 * 处理结果
		 */
		FacetField properField = response.getFacetField("proper");
		List<Count> propercounts =properField.getValues();
		if (propercounts != null) {
			//所有特征值属性
			List<String> propers=new ArrayList();
			for (Count count : propercounts) {
				if (count.getCount() != 0) {
					propers.add(count.getName());
				}
			}
			//进行第二次查询
			if(propers.size()>0){
				SolrQuery query=new SolrQuery(); 
				if(!isEmpty(map1, "keyword")){
					query.setParam("q", map1.get("keyword").toString());
				}else{
					query.setParam("q", "*");
				}
				for(String proper:propers){
					query.addFacetField(proper+"_proper");
				}
				QueryResponse properRresponse = server.query(query);  
				List properlist=new ArrayList();
				Map propermap =new  HashMap();
				for(String proper:propers){
					FacetField dynamicProperField = properRresponse.getFacetField(proper+"_proper");
					List dynamicProperFieldList=new ArrayList();//返回结果集
					List<Count> dynamicPropercounts =dynamicProperField.getValues();
					if (dynamicPropercounts != null) {
						for (Count count : dynamicPropercounts) {
							if (count.getCount() != 0) {
								dynamicProperFieldList.add(count.getName()) ;
							}
						}
						propermap.put(proper, dynamicProperFieldList);
//						System.out.println(proper+":"+propermap.get(proper));
					}
				}
				properlist.add(propermap);
				returnMap.put("proper", properlist);
//				System.out.println(returnMap.get("proper"));
				
			}
			
		}

关于 之后的查询 就不多解释了。就通过传递的业务参数来判断是否为 动态属性值。

展开阅读全文

没有更多推荐了,返回首页