转载请标明出处:http://www.jb51.cc/article/p-uyrrhjxl-bam.html
在一些电商网站中,有部分这样的搜索需求:
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的字段是哪一个。
那么,分两次查询。
<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")); } }关于 之后的查询 就不多解释了。就通过传递的业务参数来判断是否为 动态属性值。 原文链接:https://www.f2er.com/javaschema/284379.html