中通快中通速递单号查询询5368 7715-0493

搜索引擎之阿堂Solr学习笔记系列7(进阶篇:Solr的自动补全功能)
本篇文章,阿堂将和大家分享sorl的高级应用自动补全功能。实际上,我们在在一些电商平台上购物就可以经常看到自动补全功能。
如京东网上的截图所示
设想你想在你的在线商店中,给用户一些提示,比如商品的名称。假设我们的索引构建如下:&
&&field&name="id"&type="string"&indexed="true"&stored="true"&multiValued="false"&required="true"/&&
&&field&name="title"&type="textik"&indexed="true"&stored="true"&multiValued="false"&/&&
&&field&name="description"&type="text"&indexed="true"&stored="true"&multiValued="false"&/&
textik类型的定义为:
开始前,首先考虑你要实现的功能:是要实现一个名字的提示,还是全名的提示。这都依赖于我们的选择,我们必须为需要引导的地方设置适当的域。&
在单词的情况下,我们使用的域也即一个token。在这种情况下,域名为title就足够了。但是,这属于一个词干,analysis的操作都在词干上,因此,我们最好换一个其他的类型。&
我们使用一个不同的域配置来定义全名提示--最好一个未被定义的域。但是我们不能使用基于类似string这种类型的域,基于这个原因,我们定义为一下的域:
textik类型的定义为:&
为了不影响原有数据的格式,将原数据进行拷贝:&
为了使用这个数据,我们准备了一个简单的查询语句:&
q=*:*&facet=true&facet.field=FIELD&facet.mincount=1&facet.prefix=USER_QUERY
需要替换的地方:&
&& FIELD:我们打算提供建议的域,在本例中域名为title
或title_auto&
&& USER_QUERY:用户输入的字符&
这里可以设置rows=0,这样可以只返回facet的结果,而没有查询结果。当然这不是必须的。&
查询的一个例子可以这样写:&
fl=id,name&rows=0&q=*:*&facet=true&facet.field=name_auto&facet.mincount=1&facet.prefix=你们
查询结果会返回这样的结果:&
&&response&&
&&lst&name="responseHeader"&&
&&int&name="status"&0&/&/span&int&&
&&int&name="QTime"&0&/&/span&int&&
&&result&name="response"&numFound="4"&start="0"/&&
&&lst&name="facet_counts"&&
&&lst&name="facet_queries"/&&
&&lst&name="facet_fields"&&
&&lst&name="title_auto"&&
&&int&name="你们"&2&/&/span&int&&
&&int&name="你们好"&1&/&/span&int&&
&&int&name="你们好吗"&1&/&/span&int&&
&&lst&name="facet_dates"/&&/&/span&lst&&
&&response&
阿堂通过代码测试效果截图如下
另外,阿堂附上了测试完整代码
public class SolrjCompleteContents {
&&& public
static void main(String[] args)
CommonsHttpSolrServer service=
&&& service =
CommonsHttpSolrServer("http://localhost:9999/solr/");&&&
&&& } catch
(MalformedURLException e1)
e1.printStackTrace();&&&
&&& List list =
new ArrayList();&&
//查询响应结果
QueryResponse queryResponse = new
QueryResponse();&&
//查询传输参数封装
&&& SolrQuery
query = new SolrQuery();&&
query.setFacet(true);&&
query.setRows(0);&&
query.setQuery("title:你们");&&
query.setFacetPrefix("你们");&
query.addFacetField("title_auto");
&& query.setFacetLimit(20);
System.out.println("query.toString() =
"+query.toString());&&
&& queryResponse =
service.query(query);&
&& NamedListnl =
queryResponse.getResponse();&
&& System.out.println("nl =
&& NamedListnl2 =
(NamedList)nl.get("facet_counts");&&
&& NamedListnl3 =
(NamedList)nl2.get("facet_fields");&&
&& NamedListnl4 =
(NamedList)nl3.get("title_auto");&&
&& System.out.println("nl4.size()
= "+nl4.size());&&
&& Iterator& it =
nl4.iterator();
&& while (it.hasNext()) {
&& Entry entry =
it.next();&&
System.out.println(entry.getKey() + "____" +
entry.getValue());&
&&& } catch
(Exception e) {
e.printStackTrace();&&
这里说一下他的一些常用的功能。&
第一个是显示用户的一些额外的信息,比如当你选择某个提示词时,显示的结果的数量。这是一个很有意思的特性。
另一个是使用facet.sort参数进行排序。这依赖于你的需求,我们可以按文档的数量排序(默认方式,设参数为true即可),或者按字母序排序(设为false)。&
我们也可以通过设置facet.mincount来显示比指定的数量更多的提示词。&
另外一个很好的特性是提示词不仅可以通过用户的类型获取,还可以通过其他的属性获取,这类似于类别。举个例子,我们想给用户展示家庭用品相关的商品,我们假设现在用户对DVD类型的商品并不感兴趣,这样我们添加一个参数:&fq=department:homeApplications(假设有这个department)。通过这样的一个查询,你就不需要在所有的索引中匹配了,而是在我们选择的department里选择。&
跟其他方法一样,它有优点,也有缺点。优点就是易于使用、没有额外的组件依赖,并且能将结果约束在一个很小的范围内来更好的匹配用户的需求;另外一个很大的优点是它对每个提示词都附带了结果的统计。缺点就是需要添加额外的类型和字段;另外由于其facet的机制,对机器性能和load都非常消耗。
实际上,上面阿堂演示分享的只是自动补全的基本功能,要想真正到电商平台的分类功能展示效果,还需要进行数据分类的详细设计,当然,这不是本篇文章讨论的范围,属于电商平台数据库的设计,要要分成多种数据表,如分类表,商品明细表,商品附加属性表及扩展表
等数据表,这样就可以通过自动补全功能展示非常丰富的效果了。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。solr(44)
&&Facet&是&solr&的高级搜索功能之一&,&可以给用户提供更友好的搜索体验&.&在搜索关键字的同时&,能够按照&Facet&的字段进行分组并统计&.
一般代表了实体的某种公共属性&,&如商品的分类&,&商品的制造厂家&,&书籍的出版商等等&.
&字段的要求
Facet&的字段必须被索引&.&一般来说该字段无需分词&,&无需存储&.
无需分词是因为该字段的值代表了一个整体概念&,&如电脑的品牌&”&联想&”&代表了一个整体概念&,&如果拆成&”&联&”,”&想&”&两个字都不具有实际意义&.&另外该字段的值无需进行大小写转换等处理&,&保持其原貌即可&.
无需存储是因为一般而言用户所关心的并不是该字段的具体值&,&而是作为对查询结果进行分组的一种手段&,&用户一般会沿着这个分组进一步深入搜索&.
对于一般查询而言&,&分词和存储都是必要的&.&比如&CPU&类型&”Intel&酷睿&2&双核&P7570”,拆分成&”Intel”,”&酷睿&”,”P7570”&这样一些关键字并分别索引&,&可能提供更好的搜索体验&.&但是如果将&CPU&作为&Facet&字段&,&最好不进行分词&.&这样就造成了矛盾&,&解决方法为&,将&CPU&字段设置为不分词不存储&,&然后建立另外一个字段为它的&COPY,&对这个&COPY&的字段进行分词和存储&.
schema.xml
&&&&&&&&&&fieldType name=&string& class=&solr.StrField& omitNorms=&true&/&
&&&&&&&&&&fieldType name=&tokened& class=&solr.TextField& &
&&&&&&&&&&&&&&&&&&&analyzer&
&&&&&&&&&&&&&&&&&&&……
&&&&&&&&&&&&&&&&&&&&/analyzer&
&&&&&&&&&&/fieldType&
&&&&&&&&&……
&&&&&&&&&&field name=”cpu” type=”string” indexed=”true” stored=”false”/&
&&&&&&&&&&field name=”cpuCopy” type=” tokened” indexed=”true” stored=”true”/&
&&&&&&&&&……
&copyField source=&cpu& dest=&cpuCopy&/&
Solr&的默认&requestHandler(org.apache.ponent.SearchHandler)&已经包含了&Facet&组件&(org.apache.ponent.FacetComponent).&如果自定义&requestHandler&或者对默认的&requestHandler&自定义组件列表&,&那么需要将&Facet&加入到组件列表中去&.
solrconfig.xml
&requestHandler name=&standard& class=&solr.SearchHandler& default=&true&&
&arr name=&components&&
&str&自定义组件名&/str&
&str&facet&/str&
&/requestHandler&
进行&Facet&查询需要在请求参数中加入&”facet=on”&或者&”facet=true”&只有这样&Facet&组件才起作用&.
Facet&字段通过在请求中加入&”facet.field”&参数加以声明&,&如果需要对多个字段进行&Facet查询&,&那么将该参数声明多次&.&比如
/select?q=联想
&facet.field=cpu
&facet.field=videoCard
返回结果&:
&lst name=&facet_counts&&
&&&&&lst name=&facet_queries&/&
&&&&&lst name=&facet_fields&&
&&&&&lst name=&cpu&&
&&&&&int name=&Intel&酷睿2双核&T6600&&48&/int&
&&&&int name=&Intel&奔腾双核&T4300&&28&/int&
&int name=&Intel&酷睿2双核&P8700&&18&/int&
&int name=&Intel&酷睿2双核&T6570&&11&/int&
&int name=&Intel&酷睿2双核&T6670&&11&/int&
&int name=&Intel&奔腾双核&T4400&&9&/int&
&int name=&Intel&酷睿2双核&P7450&&9&/int&
&int name=&Intel&酷睿2双核&T5870&&8&/int&
&int name=&Intel&赛扬双核&T3000&&7&/int&
&int name=&Intel&奔腾双核&SU4100&&6&/int&
&int name=&Intel&酷睿2双核&P8400&&6&/int&
&int name=&Intel&酷睿2双核&SU7300&&5&/int&
&int name=&Intel&酷睿&i3 330M&&4&/int&
&&&&&/lst&
&&&&&lst name=&videoCard&&
&&&&&&&int name=&ATI Mobility Radeon HD 4&&63&/int&
&&&&&&&int name=&NVIDIA GeForce G 105M&&24&/int&
&int name=&NVIDIA GeForce GT 240M&&21&/int&
&int name=&NVIDIA GeForce G 103M&&8&/int&
&int name=&NVIDIA GeForce GT 220M&&8&/int&
&int name=&NVIDIA GeForce 9400M G&&7&/int&
&int name=&NVIDIA GeForce G 210M&&6&/int&
&&&&&&&&&&/lst&
&&&&&&&&&&lst name=&facet_dates&/&
各个&Facet&字段互不影响&,&且可以针对每个&Facet&字段设置查询参数&.&以下介绍的参数既可以应用于所有的&Facet&字段&,&也可以应用于每个单独的&Facet&字段&.&应用于单独的字段时通过
f.字段名.参数名=参数值
这种方式调用&.&比如&facet.prefix&参数应用于&cpu&字段&,&可以采用如下形式
f.cpu.facet.prefix=Intel
表示&Facet&字段值的前缀&.&比如&”facet.field=cpu&facet.prefix=Intel”,&那么对&cpu字段进行&Facet&查询&,&返回的&cpu&都是以&”Intel”&开头的&,”AMD”&开头的&cpu&型号将不会被统计在内&.
表示&Facet&字段值以哪种顺序返回&.&可接受的值为&true(count)|false(index,lex). true(count)&表示按照&count&值从大到小排列&. false(index,lex)&表示按照字段值的自然顺序(&字母&,&数字的顺序&)&排列&.&默认情况下为&true(count).&当&facet.limit&值为负数时&,默认&facet.sort= false(index,lex).
限制&Facet&字段返回的结果条数&.&默认值为&100.&如果此值为负数&,&表示不限制&.
返回结果集的偏移量&,&默认为&0.&它与&facet.limit&配合使用可以达到分页的效果&.
限制了&Facet&字段值的最小&count,&默认为&0.&合理设置该参数可以将用户的关注点集中在少数比较热门的领域&.
默认为&””,&如果设置为&true&或者&on,&那么将统计那些该&Facet&字段值为&null&的记录.
取值为&enum&或&fc,&默认为&fc.&该字段表示了两种&Facet&的算法&,&与执行效率相关&.
enum&适用于字段值比较少的情况&,&比如字段类型为布尔型&,&或者字段表示中国的所有省份.Solr&会遍历该字段的所有取值&,&并从&filterCache&里为每个值分配一个&filter(&这里要求&solrconfig.xml&里对&filterCache&的设置足够大&).&然后计算每个&filter&与主查询的交集&.
fc(&表示&Field Cache)&适用于字段取值比较多&,&但在每个文档里出现次数比较少的情况&.Solr&会遍历所有的文档&,&在每个文档内搜索&Cache&内的值&,&如果找到就将&Cache&内该值的count&加&1.
当&facet.method=enum&时&,&此参数其作用&,minDf&表示&minimum document frequency.&也就是文档内出现某个关键字的最少次数&.&该参数默认值为&0.&设置该参数可以减少&filterCache&的内存消耗&,&但会增加总的查询时间&(&计算交集的时间增加了&).&如果设置该值的话&,官方文档建议优先尝试&25-50&内的值&.
日期类型的字段在文档中很常见&,&如商品上市时间&,&货物出仓时间&,&书籍上架时间等等&.&某些情况下需要针对这些字段进行&Facet.&不过时间字段的取值有无限性&,&用户往往关心的不是某个时间点而是某个时间段内的查询统计结果&. Solr&为日期字段提供了更为方便的查询统计方式&.当然&,&字段的类型必须是&DateField(&或其子类型&).
需要注意的是&,&使用&Date Facet&时&,&字段名&,&起始时间&,&结束时间&,&时间间隔这&4&个参数都必须提供&.
与&Field Facet&类似&,Date Facet&也可以对多个字段进行&Facet.&并且针对每个字段都可以单独设置参数&.
该参数表示需要进行&Date Facet&的字段名&,&与&facet.field&一样&,&该参数可以被设置多次&,&表示对多个字段进行&Date Facet.
起始时间&,&时间的一般格式为&” T23:59:59Z”,&另外可以使用&”NOW”,”YEAR”,”MONTH”&等等&,&具体格式可以参考&org.apache.solr.schema. DateField&的&java doc.
结束时间&.
时间间隔&.&如果&start&为&,end&为&.gap&设置为&”+1MONTH”&表示间隔1&个月&,&那么将会把这段时间划分为&12&个间隔段&.&注意&”+”&因为是特殊字符所以应该用&”%2B”&代替&.
取值可以为&true|false,&默认为&false.&它表示&gap&迭代到&end&处采用何种处理&.&举例说明&start&为&,end&为&,gap&为&”+1MONTH”,hardend&为&false&的话最后一个时间段为&&至&;hardend&为&true&的话最后一个时间段为&&至&.
取值范围为&before|after|between|none|all,&默认为&none.
before&会对&start&之前的值做统计&.
after&会对&end&之后的值做统计&.
between&会对&start&至&end&之间所有值做统计&.&如果&hardend&为&true&的话&,&那么该值就是各个时间段统计值的和&.
none&表示该项禁用&.
all&表示&before,after,all&都会统计&.
&facet.date=date
&facet.date.start=T0:0:0Z
&facet.date.end=T0:0:0Z
&facet.date.gap=%2B1MONTH
&facet.date.other=all
返回结果&:
&lst name=&facet_counts&&
&&&&&&&&&&lst name=&facet_queries&/&
&&&&&&&&&&lst name=&facet_fields&/&
&&&&&&&&&&lst name=&facet_dates&&
&&&&&int name=&T00:00:00Z&&5&/int&
&int name=&T00:00:00Z&&7&/int&
&int name=&T00:00:00Z&&4&/int&
&int name=&T00:00:00Z&&3&/int&
&int name=&T00:00:00Z&&7&/int&
&int name=&T00:00:00Z&&3&/int&
&int name=&T00:00:00Z&&6&/int&
&int name=&T00:00:00Z&&7&/int&
&int name=&T00:00:00Z&&2&/int&
&int name=&T00:00:00Z&&4&/int&
&int name=&T00:00:00Z&&1&/int&
&int name=&T00:00:00Z&&5&/int&
&str name=&gap&&+1MONTH&/str&
&date name=&end&&T00:00:00Z&/date&
&int name=&before&&180&/int&
&int name=&after&&5&/int&
&int name=&between&&54&/int&
Facet Query&利用类似于&filter query&的语法提供了更为灵活的&Facet.&通过&facet.query&参数&,&可以对任意字段进行筛选&.
&facet.query=date:[T0:0:0Z TO T0:0:0Z]
&facet.query=date:[T0:0:0Z TO T0:0:0Z]
返回结果&:
&lst name=&facet_counts&&
&lst name=&facet_queries&&
&&&&&int name=&date:[T0:0:0Z TO T0:0:0Z]&&5&/int&
&int name=&date:[T0:0:0Z TO T0:0:0Z]&&3&/int&
&&&&&&&&&&lst name=&facet_fields&/&
&&&&&&&&&&lst name=&facet_dates&/&&/lst&
&facet.query=date:[T0:0:0Z TO T0:0:0Z]
&facet.query=price:[* TO 5000]
返回结果&:
&lst name=&facet_counts&&
&&&lst name=&facet_queries&&
&&&&&int name=&date:[T0:0:0Z TO T0:0:0Z]&&5&/int&
&int name=&price:[* TO 5000]&&116&/int&
&&&lst name=&facet_fields&/&
&&&lst name=&facet_dates&/&
&facet.query=cpu:[A TO G]
返回结果&:
&lst name=&facet_counts&&
&&&&&&&&&&lst name=&facet_queries&&
&&&&&&&&&&&&&&&&&&&&int name=&cpu:[A TO G]&&11&/int&
&&&&&&&&&&lst name=&facet_fields&/&
&&&&&&&&&&lst name=&facet_dates&/&
可以用&key&操作符为&Facet&字段取一个别名&.
&facet.field={!key=中央处理器}cpu
&facet.field={!key=显卡}videoCard
返回结果&:
&lst name=&facet_counts&&
&&&&&&&&&&lst name=&facet_queries&/&
&&&&&&&&&&lst name=&facet_fields&&
&&&&&&&&&&lst name=&中央处理器&&
&&&&&&&&&&int name=&Intel&酷睿2双核&T6600&&48&/int&
&&&&&&&&&&int name=&Intel&奔腾双核&T4300&&28&/int&
&int name=&Intel&酷睿2双核&P8700&&18&/int&
&int name=&Intel&酷睿2双核&T6570&&11&/int&
&int name=&Intel&酷睿2双核&T6670&&11&/int&
&int name=&Intel&奔腾双核&T4400&&9&/int&
&int name=&Intel&酷睿2双核&P7450&&9&/int&
&int name=&Intel&酷睿2双核&T5870&&8&/int&
&int name=&Intel&赛扬双核&T3000&&7&/int&
&int name=&Intel&奔腾双核&SU4100&&6&/int&
&int name=&Intel&酷睿2双核&P8400&&6&/int&
&int name=&Intel&酷睿2双核&SU7300&&5&/int&
&int name=&Intel&酷睿&i3 330M&&4&/int&
&&&&&/lst&
&&&&&lst name=&显卡&&
&&&&&&&int name=&ATI Mobility Radeon HD 4&&63&/int&
&&&&&&&int name=&NVIDIA GeForce G 105M&&24&/int&
&int name=&NVIDIA GeForce GT 240M&&21&/int&
&int name=&NVIDIA GeForce G 103M&&8&/int&
&int name=&NVIDIA GeForce GT 220M&&8&/int&
&int name=&NVIDIA GeForce 9400M G&&7&/int&
&int name=&NVIDIA GeForce G 210M&&6&/int&
&&&&&&&&&&/lst&
&&&&&&&&&&lst name=&facet_dates&/&
&操作符和&ex&操作符
当查询使用&filter query&的时候&,&如果&filter query&的字段正好是&Facet&字段&,&那么查询结果往往被限制在某一个值内&.
&fq=screenSize:14
&facet.field=screenSize
返回结果&:
&lst name=&facet_counts&&
&&&&&&&&&&lst name=&facet_queries&/&
&&&&&&&&&&lst name=&facet_fields&&
&&&&&&&&&&&&&&&&&&&&lst name=& screenSize&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int name=&14.0&&107&/int&
&int name=&10.2&&0&/int&
&int name=&11.1&&0&/int&
&int name=&11.6&&0&/int&
&int name=&12.1&&0&/int&
&int name=&13.1&&0&/int&
&int name=&13.3&&0&/int&
&int name=&14.1&&0&/int&
&int name=&15.4&&0&/int&
&int name=&15.5&&0&/int&
&int name=&15.6&&0&/int&
&int name=&16.0&&0&/int&
&int name=&17.0&&0&/int&
&int name=&17.3&&0&/int&
&&&&&&&&&&/lst&
&&&&&&&&&&lst name=&facet_dates&/&
可以看到&,&屏幕尺寸&(screenSize)&为&14&寸的产品共有&107&件&,&其它尺寸的产品的数目都是0,&这是因为在&filter&里已经限制了&screenSize:14.&这样&,&查询结果中&,&除了&screenSize=14&的这一项之外&,&其它项目没有实际的意义&.
有些时候&,&用户希望把结果限制在某一范围内&,&又希望查看该范围外的概况&.&比如上述情况&,既要把查询结果限制在&14&寸屏的笔记本&,&又想查看一下其它屏幕尺寸的笔记本有多少产品&.&这个时候需要用到&tag&和&ex&操作符&.
tag&就是把一个&filter&标记起来&,ex(exclude)&是在&Facet&的时候把标记过的&filter&排除在外&.
&fq={!tag=aa}screenSize:14
&facet.field={!ex=aa}screenSize
返回结果&:
&lst name=&facet_counts&&
&&&&&&&&&&lst name=&facet_queries&/&
&&&&&&&&&&lst name=&facet_fields&&
&&&&&&&&&&&&&&&&&&&&lst name=& screenSize&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int name=&14.0&&107&/int&
&int name=&14.1&&40&/int&
&int name=&13.3&&34&/int&
&int name=&15.6&&22&/int&
&int name=&15.4&&8&/int&
&int name=&11.6&&6&/int&
&int name=&12.1&&5&/int&
&int name=&16.0&&5&/int&
&int name=&15.5&&3&/int&
&int name=&17.0&&3&/int&
&int name=&17.3&&3&/int&
&int name=&10.2&&1&/int&
&int name=&11.1&&1&/int&
&int name=&13.1&&1&/int&
&&&&&&&&&&/lst&
&&&&&&&&&&lst name=&facet_dates&/&
这样其它屏幕尺寸的统计信息就有意义了&.
&对&Facet&的支持
SolrServer server =&getSolrServer();//获取SolrServer
SolrQuery query =&new&SolrQuery();//建立一个新的查询
query.setQuery(&*:*&);
query.setFacet(true);//设置facet=on
query.addFacetField(new&String[] {&&cpu&,&&videoCard&&});//设置需要facet的字段
query.setFacetLimit(10);//限制facet返回的数量
QueryResponse response = server.query(query);
List&FacetField& facets = response.getFacetFields();//返回的facet列表
for&(FacetField&facet : facets) {
System.out.println(facet.getName());
&&&&System.out.println(&----------------&);
&&&&List&Count& counts = facet.getValues();
&&&&for&(Count count : counts) {
&&&&&&&&System.out.println(count.getName() +&&:&&+
count.getCount());
&&&&System.out.println();
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:16893次
排名:千里之外
原创:25篇
转载:142篇
(6)(5)(12)(3)(8)(4)(26)(16)(2)(19)(15)(42)(9)Solr Facet 查询 - 超越昨天的自己! - ITeye技术网站
博客分类:
Solr Facet查询
转载请出自出处:
Facet是solr的高级搜索功能之一,可以给用户提供更友好的搜索体验.在搜索关键字的同时,能够按照Facet的字段进行分组并统计。例如下图所示,你上淘宝,输入“电脑”进行搜索,就会出现品牌分类,价格范围等分类,这个就叫Facet。
二)Solr Facet类型
Solr提供了4种类型的Fact
&lst name="facet_counts"&
&lst name="facet_queries"/&
&lst name="facet_fields"/&
&lst name="facet_dates"/&
&lst name="facet_ranges"/&
facet_queries:代表自定义条件查询facet,类似数据库的count函数
facet_fields
:代表根据字段分组查询,类似数据库的group by count的组合
facet_dates :根据日期区间分组查询
facet_ranges:当然了,日期有区间,数字也有,这个就是根据数字分组查询
三)Solr Facet组件
Solr的默认requestHandler已经包含了Facet组件(solr.FacetComponent).如果自定义requestHandler或者对默认的requestHandler自定义组件列表,那么需要将Facet加入到组件列表中去.
四)facet query
Facet Query 用户自定义条件查询facet,他提供了非常灵活的Facet.通过facet.query参数,可以对任意字段进行筛选.下面通过实例来阐述。基本上他的用法,都会在我实例中体现出来
例一:日期区间查询
&facet=true
&facet.query=date:[T0:0:0Z TO T0:0:0Z]
&facet.query=date:[T0:0:0Z TO T0:0:0Z]
返回结果如下:
&lst name="facet_counts"&
&lst name="facet_queries"&
&int name="date:[T0:0:0Z TO T0:0:0Z]"&5&/int&
&int name="date:[T0:0:0Z TO T0:0:0Z]"&3&/int&
&lst name="facet_fields"/&
&lst name="facet_dates"/&
例2:数字区间统计
&facet.query=date:[T0:0:0Z TO T0:0:0Z]
&facet.query=price:[* TO 5000]
&lst name="facet_counts"&
&lst name="facet_queries"&
&int name="date:[T0:0:0Z TO T0:0:0Z]"&5&/int&
&int name="price:[* TO 5000]"&116&/int&
&lst name="facet_fields"/&
&lst name="facet_dates"/&
例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 Facet
Facet字段通过在请求中加入facet.field参数加以声明,如果需要对多个字段进行Facet查询,那么将该参数声明多次.这就是类似于数据库的group by 加上count的功能,非常的灵活。
实例一:最简单的field facet
&facet=true
&facet.field=brand
&facet.field=price
返回结果如下
"facet_counts":{
"facet_queries":{},
"facet_fields":{
"惠普",2],
"facet_dates":{},
"facet_ranges":{}}}
从返回结果可以看出各个field字段互不影响;而且可以针对,下面实例会体现
每个Facet字段设置查询参数.以下介绍的参数既可以应用于所有的Facet字段,也可以应用于每个单独的Facet字段.应用于单独的字段时通过下面语法实现
f.字段名.参数名=参数值
例如:将facet.prefix参数应用于brand字段,可以采用如下形式
&facet.field=brand
&facet.field=price
&f.brand.facet.prefix=联
返回结果如下:
"facet_counts":{
"facet_queries":{},
"facet_fields":{
"联想",3],
"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
日期类型的字段在文档中很常见,如商品上市时间,货物出仓时间,书籍上架时间等等.某些情况下需要针对这些字段进行Facet.不过时间字段的取值有无限性,用户往往关心的不是某个时间点而是某个时间段内的查询统计结果. Solr为日期字段提供了更为方便的查询统计方式.当然,字段的类型必须是DateField(或其子类型)。
需要注意的是,使用Date Facet时,字段名,起始时间,结束时间,时间间隔这4个参数都必须提供.与Field Facet类似,Date Facet也可以对多个字段进行Facet.并且针对每个字段都可以单独设置参数。
简单实例参考
&facet.date=birthday
&facet.date.start=T09:15:00Z
&facet.date.end=T09:15:00Z
&facet.date.gap=%2B1MONTH
返回结果如下所示
"facet_counts":{
"facet_queries":{},
"facet_fields":{},
"facet_dates":{
"birthday":{
"T09:15:00Z":0,
"T09:15:00Z":0,
"T09:15:00Z":0,
"T09:15:00Z":0,
"T09:15:00Z":0,
"T09:15:00Z":0,
"T09:15:00Z":0,
"T09:15:00Z":0,
"T09:15:00Z":0,
"T09:15:00Z":1,
"T09:15:00Z":5,
"T09:15:00Z":3,
"gap":"+1MONTH",
"start":"T09:15:00Z",
"end":"T09:15:00Z"}},
"facet_ranges":{}}}
Date Facet参数说明
1).facet.date
该参数表示需要进行Date Facet的字段名,与facet.field一样,该参数可以被设置多次,表示对多个字段进行Date Facet.
2).facet.date.start
起始时间,时间格式为T23:59:59Z
3).facet.date.end
4).facet.date.gap
时间间隔.如果start为,end为.gap设置为+1MONTH表示间隔1个月,那么将会把这段时间划分为12个间隔段.
注意+因为是特殊字符所以应该用%2B代替.
5).facet.date.hardend
取值可以为true|false,默认为false.它表示gap迭代到end处采用何种处理.举例说明start为,end为,gap为+1MONTH,
hardend为false的话最后一个时间段为至;
hardend为true的话最后一个时间段为至.
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=T09:15:00Z
&facet.date.end=T09: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":{
"T09:15:00Z":5,
"T09:15:00Z":3,
"gap":"+1MONTH",
"start":"T09:15:00Z",
"end":"T09:15:00Z",
"before":0,
"after":0,
"between":9}},
"facet_ranges":{}}}
七)Facet Range
范围统计分组统计,跟Date Facet一样,只是他们定位的字段的类型不同,Data Fact是做日期的分组统计的,而Fact Range是做数字分组统计的,在次强调,是做数字分组统计的,对于字符串,日期是不可以的。
参数跟上面的Date Facet基本一致,如下,就不做解释了,参考Date Facet的各个参数
1. facet.range
2. facet.range.start
3. facet.range.end
4. facet.range.gap
5. facet.range.hardend
6. facet.range.other
7. facet.range.include
&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":{
"counts":[
"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":{
"facet_dates":{},
"facet_ranges":{}}}
从返回的结果可以看到fq将查询的结果集限制在了price 在1000 至 2000之间,其他范围的统计没有实际意义。
有些时候,用户希望把结果限制在某一个范围以内,又希望查看该范围外的概况,像上述情况,用户想把结果限制在(price)之间,但是又想查看其他价格区间有多少产品。这个时候需要用到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":{
"facet_dates":{},
"facet_ranges":{}}}
这样其它价格区间的统计信息就有意义了.
十)Facet 字段设计
一、Facet字段的要求
Facet的字段必须被索引.一般来说该字段无需分词,无需存储.
无需分词是因为该字段的值代表了一个整体概念,如电脑的品牌”联想”代表了一个整体概念,如果拆成”联”,”想”两个字都不具有实际意义.另外该字段的值无需进行大小写转换等处理,保持其原貌即可.
无需存储是因为一般而言用户所关心的并不是该字段的具体值,而是作为对查询结果进行分组的一种手段,用户一般会沿着这个分组进一步深入搜索.
二、特殊情况
对于一般查询而言,分词和存储都是必要的.比如CPU类型“Intel 酷睿2双核 P7570”,拆分成“Intel”,“酷睿”,“P7570”这样一些关键字并分别索引,可能提供更好的搜索体验.但是如果将CPU作为Facet字段,最好不进行分词.这样就造成了矛盾,解决方法为,将CPU字段设置为不分词不存储,然后建立另外一个字段为它的COPY,对这个COPY的字段进行分词和存储.
&fieldType name="string" class="solr.StrField" omitNorms="true"/&
&fieldType name="tokened" class="solr.TextField" &
&analyzer&
&/analyzer&
&/fieldType&
&field name="cpu" type="string" indexed="true" stored="false"/&
&field name="cpuCopy” type=" tokened" indexed="true" stored="true"/&
&copyField source="cpu" dest="cpuCopy"/&
http://wiki.apache.org/solr/SimpleFacetParameters
浏览: 165867 次
来自: 广州
limeng650419 写道然而并未卵并不管用
然而并未卵
这么好的文章没人看
请教下,/select??q=*:*&stats=tr ...
-&response&
-&lst na ...

我要回帖

更多关于 中通快运单号查询网 的文章

 

随机推荐