设为首页 收藏本站
查看: 1178|回复: 0

[经验分享] 8.2Solr API使用(Facet查询)

[复制链接]

尚未签到

发表于 2017-12-19 08:45:49 | 显示全部楼层 |阅读模式
  转载请出自出处:http://eksliang.iteye.com/blog/2165882
  一)概述

  >
DSC0000.jpg

  二)Solr>类型
  Solr提供了4种类型的Fact
  

<lst name="facet_counts">  <lst name="facet_queries"/>  
  <lst name="facet_fields"/>  
  <lst name="facet_dates"/>  
  <lst name="facet_ranges"/>  
  
</lst>
  


  1.>
  2.>
  3.>
  4.>  三)Solr>组件
  Solr的默认requestHandler已经包含了Facet组件(solr.FacetComponent).如果自定义requestHandler或者对默认的requestHandler自定义组件列表,那么需要将Facet加入到组件列表中去.
  四)facet query

  >  例一:日期区间查询
  

&facet=true  

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

&facet.query=date:[2009-4-1T0:0:0Z TO 2009-5-1T0:0:0Z]  

  返回结果如下:
  

<lst name="facet_counts">  <lst name="facet_queries">  
  <int name="date:[2009-1-1T0:0:0Z TO 2009-2-1T0:0:0Z]">5</int>  
  <int name="date:[2009-4-1T0:0:0Z TO 2009-5-1T0:0:0Z]">3</int>  
  
</lst>  
  <lst name="facet_fields"/>  
  <lst name="facet_dates"/>  
  
</lst>
  

  例2:数字区间统计
  

&facet=on  

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

&facet.query=price:[* TO 5000]  

  返回结果
  

<lst name="facet_counts">  <lst name="facet_queries">  
  <int name="date:[2009-1-1T0:0:0Z TO 2009-2-1T0:0:0Z]">5</int>  
  <int name="price:[* TO 5000]">116</int>  
  
</lst>  
  <lst name="facet_fields"/>  
  <lst name="facet_dates"/>  
  
</lst>
  

  例3:自定义条件
  

&facet=true  

&facet.query=brand:联想 AND price:1100  

  返回结果
  

"facet_counts":{  "facet_queries"
:{  "brand:联想 AND price:1100":1
},  "facet_fields":
{},  "facet_dates":
{},  "facet_ranges":
{}}}  

  五)Field>

  >
  实例一:最简单的field>  

&facet=true  

&facet.field=brand  

&facet.field=price  

  返回结果如下
  

"facet_counts":{  "facet_queries"
:{},  "facet_fields":
{  "brand"
:[  "苹果",4,  
  "联想",3,  
  "惠普",2],  
  "price":[  
  "1100.0",2,  
  "2200.0",2,  
  "3300.0",2,  
  "1200.0",1,  
  "2100.0",1,  
  "4400.0",1]
},  "facet_dates":
{},  "facet_ranges":
{}}}  

  从返回结果可以看出各个field字段互不影响;而且可以针对,下面实例会体现
  每个Facet字段设置查询参数.以下介绍的参数既可以应用于所有的Facet字段,也可以应用于每个单独的Facet字段.应用于单独的字段时通过下面语法实现
  1. f.字段名.参数名=参数值
  例如:将facet.prefix参数应用于brand字段,可以采用如下形式
  

&facet.field=brand  

&facet.field=price  

&f.brand.facet.prefix=联  

  返回结果如下:
  

"facet_counts":{  "facet_queries"
:{},  "facet_fields":
{  "brand"
:[  "联想",3],  
  "price":[  
  "1100.0",2,  
  "2200.0",2,  
  "3300.0",2,  
  "1200.0",1,  
  "2100.0",1,  
  "4400.0",1]
},  "facet_dates":
{},  "facet_ranges":
{}}}  

  温馨提示:上面的facet.prefix就是一个参数名,这个很容易误解为两个,因为他中间有个点
  上面介绍了facet.field参数,下面介绍field fact的其他参数
  

1).facet.prefix  表示Facet字段值的前缀.比如facet.field
=cpu&facet.prefix=Intel,那么对cpu字段进行Facet查询,返回的cpu都是以“Intel”开头的。  

2).facet.sort  表示Facet字段值以哪种顺序返回.可接受的值为true(count)
|false(index,lex). true(count)表示按照count降序; false(index,lex)表示按照字段值升序(字母,数字的顺序)排列.默认情况下为true(count).当facet.limit值为负数时,默认facet.sort= false(index,lex).  

3).facet.limit  限制Facet字段返回的结果条数.默认值为100.如果此值为负数,表示不限制.  
  

4).facet.offset  返回结果集的偏移量,默认为0.它与facet.limit配合使用可以达到分页的效果.  
  

5).facet.mincount  限制了Facet字段值的最小count,默认为0.合理设置该参数可以将用户的关注点集中在少数比较热门的领域.相当于group by having  
  

6).facet.missing  默认为””,如果设置为true或者on,那么将统计那些该Facet字段值为null的记录.  
  

7).facet.method  取值为enum或fc,默认为fc.该字段表示了两种Facet的算法,与执行效率相关.  
  enum适用于字段值比较少的情况,比如字段类型为布尔型,或者字段表示中国的所有省份.Solr会遍历该字段的所有取值,并从filterCache里为每个值分配一个filter(这里要求solrconfig.xml里对filterCache的设置足够大).然后计算每个filter与主查询的交集.  
  fc(表示Field Cache)适用于字段取值比较多,但在每个文档里出现次数比较少的情况.Solr会遍历所有的文档,在每个文档内搜索Cache内的值,如果找到就将Cache内该值的count加1.  
  

8).facet.enum.cache.minDf  当facet.method
=enum时,此参数其作用,minDf表示minimum document frequency.也就是文档内出现某个关键字的最少次数.该参数默认值为0.设置该参数可以减少filterCache的内存消耗,但会增加总的查询时间(计算交集的时间增加了).如果设置该值的话,官方文档建议优先尝试25-50内的值.  

  六)Date>
  日期类型的字段在文档中很常见,如商品上市时间,货物出仓时间,书籍上架时间等等.某些情况下需要针对这些字段进行Facet.不过时间字段的取值有无限性,用户往往关心的不是某个时间点而是某个时间段内的查询统计结果. Solr为日期字段提供了更为方便的查询统计方式.当然,字段的类型必须是DateField(或其子类型)。

  需要注意的是,使用Date>  简单实例参考
  

&facet.date=birthday  

&facet.date.start=2014-01-00T09:15:00Z  

&facet.date.end=2014-12-00T09:15:00Z  

&facet.date.gap=%2B1MONTH  

  返回结果如下所示
  

"facet_counts":{  "facet_queries"
:{},  "facet_fields":
{},  "facet_dates":
{  "birthday"
:{  "2013-12-31T09:15:00Z":0,  
  "2014-01-31T09:15:00Z":0,  
  "2014-02-28T09:15:00Z":0,  
  "2014-03-28T09:15:00Z":0,  
  "2014-04-28T09:15:00Z":0,  
  "2014-05-28T09:15:00Z":0,  
  "2014-06-28T09:15:00Z":0,  
  "2014-07-28T09:15:00Z":0,  
  "2014-08-28T09:15:00Z":0,  
  "2014-09-28T09:15:00Z":1,  
  "2014-10-28T09:15:00Z":5,  
  "2014-11-28T09:15:00Z":3,  
  "gap":"+1MONTH",  
  "start":"2013-12-31T09:15:00Z",  
  "end":"2014-12-28T09:15:00Z"
}},  "facet_ranges":
{}}}  


  Date>  

1).facet.date
  该参数表示需要进行Date>  

2).facet.date.start  起始时间,时间格式为1995
-12-31T23:59:59Z  

3).facet.date.end  结束时间.  
  

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

5).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.  

6).facet.date.other  取值范围为before
|after|between|none|all,默认为none,before会对start之前的值做统计,after会对end之后的值做统计,between会对start至end之间所有值做统计.如果hardend为true的话,那么该值就是各个时间段统计值的和.none表示该项禁用.all表示before,after,all都会统计.  

  实例参考,演示fact.date.other、跟单独对某个字段起作用
  

&facet.date=birthday  

&facet.date.start=2014-01-00T09:15:00Z  

&facet.date.end=2014-12-00T09:15:00Z  

&facet.date.gap=%2B1MONTH  

&facet.date.other=all  

&f.birthday.facet.mincount=3 --单独对某个字段起作用,把统计值小于3的过滤掉  

  返回结果如下:
  

"facet_counts":{  "facet_queries"
:{},  "facet_fields":
{},  "facet_dates":
{  "birthday"
:{  "2014-10-28T09:15:00Z":5,  
  "2014-11-28T09:15:00Z":3,  
  "gap":"+1MONTH",  
  "start":"2013-12-31T09:15:00Z",  
  "end":"2014-12-28T09:15:00Z",  
  "before":0,  
  "after":0,  
  "between":9
}},  "facet_ranges":
{}}}  

  七)Facet Range

  范围统计分组统计,跟Date>
  参数跟上面的Date>  

1. >
2. >
  
3. >
  
4. >
  
5. >
  
6. >
  
7. >  

  参考实例
  

&facet.range=price  

&facet.range.start=1000  

&facet.range.end=5000  

&facet.range.gap=1000  

&f.price.facet.mincount=2--单独对某个字段起作用,把统计值小于2的过滤掉  

  返回结果如下:
  

"facet_counts":{  "facet_queries"
:{},  "facet_fields":
{},  "facet_dates":
{},  "facet_ranges":
{  "price"
:{  "counts":[
  "1000.0",3,
  "2000.0",3,
  "3000.0",2],
  "gap":1000.0,
  "start":1000.0,
  "end":5000.0
}}}}  

  八)key 操作符
  上面已经介绍了facet的四类统计,下面介绍一下key,什么是key?
  答:key操作符可以为Facet字段取一个别名。哦原来如此简单!
  参考实例:
  参数
  

&facet=true  

&facet.query=brand:联想 AND price:1100  

  返回结果
  

"facet_counts":{  "facet_queries"
:{  "brand:联想 AND price:1100":1
},  "facet_fields":
{},  "facet_dates":
{},  "facet_ranges":
{}}}  

  参数
  

&facet=true  

&facet.query={!key=联想}brand:联想 AND price:1100  

  返回结果
  

"facet_counts":{  "facet_queries"
:{  "联想":1
},  "facet_fields":
{},  "facet_dates":
{},  "facet_ranges":
{}}}  

  从上面可以看出来,这样可以让字段名统一起来,方便我们拿到请求数据后,封装成自己的对象
  九)tag操作符和ex操作符
  这个也非常的重要,看下应用场景,当查询使用filter query 或者q的时候,如果filter query的字段正好是Facet字段,那么查询结果往往被限制在某一个值内.
  参考实例
  

&fq=price:[1000 TO 2000]  

&facet.field=price  

  返回结果
  

"facet_counts":{  "facet_queries"
:{},  "facet_fields":
{  "price"
:[  "1100.0",2,  
  "1200.0",1,  
  "2100.0",0,  
  "2200.0",0,  
  "3300.0",0,  
  "4400.0",0]
},  "facet_dates":
{},  "facet_ranges":
{}}}  

  从返回的结果可以看到fq将查询的结果集限制在了price 在1000 至 2000之间,其他范围的统计没有实际意义。
  有些时候,用户希望把结果限制在某一个范围以内,又希望查看该范围外的概况,像上述情况,用户想把结果限制在(price)1000~2000之间,但是又想查看其他价格区间有多少产品。这个时候需要用到tag和ex操作符.tag就是把一个filter标记起来,ex(exclude)是在Facet的时候把标记过的filter排除在外.
  参考实例
  

&fq={!tag=aa}price:[1000 TO 2000]  

&facet.field={!ex=aa}price  

  返回结果
  

"facet_counts":{  "facet_queries"
:{},  "facet_fields":
{  "price"
:[  "1100.0",2,  
  "2200.0",2,  
  "3300.0",2,  
  "1200.0",1,  
  "2100.0",1,  
  "4400.0",1]
},  "facet_dates":
{},  "facet_ranges":
{}}}  

  这样其它价格区间的统计信息就有意义了.
  十)Facet 字段设计
  一、Facet字段的要求

  >  无需分词是因为该字段的值代表了一个整体概念,如电脑的品牌”联想”代表了一个整体概念,如果拆成”联”,”想”两个字都不具有实际意义.另外该字段的值无需进行大小写转换等处理,保持其原貌即可.
  无需存储是因为一般而言用户所关心的并不是该字段的具体值,而是作为对查询结果进行分组的一种手段,用户一般会沿着这个分组进一步深入搜索.
  二、特殊情况
  对于一般查询而言,分词和存储都是必要的.比如CPU类型“Intel 酷睿2双核 P7570”,拆分成“Intel”,“酷睿”,“P7570”这样一些关键字并分别索引,可能提供更好的搜索体验.但是如果将CPU作为Facet字段,最好不进行分词.这样就造成了矛盾,解决方法为,将CPU字段设置为不分词不存储,然后建立另外一个字段为它的COPY,对这个COPY的字段进行分词和存储.
  

<types>  <fieldType name="string" omitNorms="true"/>  
  <fieldType name="tokened" >  
  <analyzer>  
  ……  
  </analyzer>  
  </fieldType>  
  
</types>  
  
<fields>  
  <field name="cpu" type="string" indexed="true" stored="false"/>  
  <field name="cpuCopy” type=" tokened" indexed="true" stored="true"/>  
  
</fields>  
  
<copyField source="cpu" dest="cpuCopy"/>
  

  官网API:  http://wiki.apache.org/solr/SimpleFacetParameters

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-425591-1-1.html 上篇帖子: 安装和使用solr 下篇帖子: solr 基本命令二(权重查找)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表