Solr Facet 查询
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
Solr Facet查詢
轉(zhuǎn)載請出自出處:http://eksliang.iteye.com/blog/2165882
一)概述
? ? ? ? Facet是solr的高級搜索功能之一,可以給用戶提供更友好的搜索體驗.在搜索關(guān)鍵字的同時,能夠按照Facet的字段進行分組并統(tǒng)計。例如下圖所示,你上淘寶,輸入“電腦”進行搜索,就會出現(xiàn)品牌分類,價格范圍等分類,這個就叫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"/> </lst>?
三)Solr Facet組件?
? ? ? ? ?Solr的默認requestHandler已經(jīng)包含了Facet組件(solr.FacetComponent).如果自定義requestHandler或者對默認的requestHandler自定義組件列表,那么需要將Facet加入到組件列表中去.
?
四)facet query
? ? ? ?Facet Query 用戶自定義條件查詢facet,他提供了非常靈活的Facet.通過facet.query參數(shù),可以對任意字段進行篩選.下面通過實例來闡述。基本上他的用法,都會在我實例中體現(xiàn)出來
例一:日期區(qū)間查詢
?
&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]? ? 返回結(jié)果如下:
?
?
?
<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:數(shù)字區(qū)間統(tǒng)計
?
&facet=on &facet.query=date:[2009-1-1T0:0:0Z TO 2009-2-1T0:0:0Z] &facet.query=price:[* TO 5000]?返回結(jié)果
?
?
<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:聯(lián)想 AND price:1100?返回結(jié)果
?
?
"facet_counts":{"facet_queries":{"brand:聯(lián)想 AND price:1100":1},"facet_fields":{},"facet_dates":{},"facet_ranges":{}}}?
?
五)Field Facet
? ? ? ?Facet字段通過在請求中加入facet.field參數(shù)加以聲明,如果需要對多個字段進行Facet查詢,那么將該參數(shù)聲明多次.這就是類似于數(shù)據(jù)庫的group by 加上count的功能,非常的靈活。
實例一:最簡單的field facet
?
&facet=true &facet.field=brand &facet.field=price?返回結(jié)果如下
?
?
"facet_counts":{"facet_queries":{},"facet_fields":{"brand":["蘋果",4,"聯(lián)想",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":{}}}?從返回結(jié)果可以看出各個field字段互不影響;而且可以針對,下面實例會體現(xiàn)
?
?
每個Facet字段設(shè)置查詢參數(shù).以下介紹的參數(shù)既可以應用于所有的Facet字段,也可以應用于每個單獨的Facet字段.應用于單獨的字段時通過下面語法實現(xiàn)
?
f.字段名.參數(shù)名=參數(shù)值?例如:將facet.prefix參數(shù)應用于brand字段,可以采用如下形式
?
?
&facet.field=brand &facet.field=price &f.brand.facet.prefix=聯(lián)?返回結(jié)果如下:
?
"facet_counts":{"facet_queries":{},"facet_fields":{"brand":["聯(lián)想",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就是一個參數(shù)名,這個很容易誤解為兩個,因為他中間有個點
上面介紹了facet.field參數(shù),下面介紹field fact的其他參數(shù)
?
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)表示按照字段值升序(字母,數(shù)字的順序)排列.默認情況下為true(count).當facet.limit值為負數(shù)時,默認facet.sort= false(index,lex). 3).facet.limit限制Facet字段返回的結(jié)果條數(shù).默認值為100.如果此值為負數(shù),表示不限制. 4).facet.offset返回結(jié)果集的偏移量,默認為0.它與facet.limit配合使用可以達到分頁的效果. 5).facet.mincount限制了Facet字段值的最小count,默認為0.合理設(shè)置該參數(shù)可以將用戶的關(guān)注點集中在少數(shù)比較熱門的領(lǐng)域.相當于group by having 6).facet.missing默認為””,如果設(shè)置為true或者on,那么將統(tǒng)計那些該Facet字段值為null的記錄. 7).facet.method取值為enum或fc,默認為fc.該字段表示了兩種Facet的算法,與執(zhí)行效率相關(guān).enum適用于字段值比較少的情況,比如字段類型為布爾型,或者字段表示中國的所有省份.Solr會遍歷該字段的所有取值,并從filterCache里為每個值分配一個filter(這里要求solrconfig.xml里對filterCache的設(shè)置足夠大).然后計算每個filter與主查詢的交集.fc(表示Field Cache)適用于字段取值比較多,但在每個文檔里出現(xiàn)次數(shù)比較少的情況.Solr會遍歷所有的文檔,在每個文檔內(nèi)搜索Cache內(nèi)的值,如果找到就將Cache內(nèi)該值的count加1. 8).facet.enum.cache.minDf當facet.method=enum時,此參數(shù)其作用,minDf表示minimum document frequency.也就是文檔內(nèi)出現(xiàn)某個關(guān)鍵字的最少次數(shù).該參數(shù)默認值為0.設(shè)置該參數(shù)可以減少filterCache的內(nèi)存消耗,但會增加總的查詢時間(計算交集的時間增加了).如果設(shè)置該值的話,官方文檔建議優(yōu)先嘗試25-50內(nèi)的值. ??
?
六) Date Facet
? ? ? ?日期類型的字段在文檔中很常見,如商品上市時間,貨物出倉時間,書籍上架時間等等.某些情況下需要針對這些字段進行Facet.不過時間字段的取值有無限性,用戶往往關(guān)心的不是某個時間點而是某個時間段內(nèi)的查詢統(tǒng)計結(jié)果. Solr為日期字段提供了更為方便的查詢統(tǒng)計方式.當然,字段的類型必須是DateField(或其子類型)。
? ? ? ? 需要注意的是,使用Date Facet時,字段名,起始時間,結(jié)束時間,時間間隔這4個參數(shù)都必須提供.與Field Facet類似,Date Facet也可以對多個字段進行Facet.并且針對每個字段都可以單獨設(shè)置參數(shù)。
簡單實例參考
&facet.date=birthday &facet.date.start=2014-01-00T09:15:00Z &facet.date.end=2014-12-00T09:15:00Z &facet.date.gap=%2B1MONTH?返回結(jié)果如下所示
"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 Facet參數(shù)說明
?
1).facet.date該參數(shù)表示需要進行Date Facet的字段名,與facet.field一樣,該參數(shù)可以被設(shè)置多次,表示對多個字段進行Date Facet. 2).facet.date.start起始時間,時間格式為1995-12-31T23:59:59Z 3).facet.date.end結(jié)束時間. 4).facet.date.gap時間間隔.如果start為2009-1-1,end為2010-1-1.gap設(shè)置為+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之前的值做統(tǒng)計,after會對end之后的值做統(tǒng)計,between會對start至end之間所有值做統(tǒng)計.如果hardend為true的話,那么該值就是各個時間段統(tǒng)計值的和.none表示該項禁用.all表示before,after,all都會統(tǒng)計. ??
?實例參考,演示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 --單獨對某個字段起作用,把統(tǒng)計值小于3的過濾掉?返回結(jié)果如下:
"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
? ? ? 范圍統(tǒng)計分組統(tǒng)計,跟Date Facet一樣,只是他們定位的字段的類型不同,Data Fact是做日期的分組統(tǒng)計的,而Fact Range是做數(shù)字分組統(tǒng)計的,在次強調(diào),是做數(shù)字分組統(tǒng)計的,對于字符串,日期是不可以的。
參數(shù)跟上面的Date Facet基本一致,如下,就不做解釋了,參考Date Facet的各個參數(shù)
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--單獨對某個字段起作用,把統(tǒng)計值小于2的過濾掉?返回結(jié)果如下:
"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 操作符
上面已經(jīng)介紹了facet的四類統(tǒng)計,下面介紹一下key,什么是key?
答:key操作符可以為Facet字段取一個別名。哦原來如此簡單!
參考實例:
參數(shù) &facet=true &facet.query=brand:聯(lián)想 AND price:1100 返回結(jié)果 "facet_counts":{"facet_queries":{"brand:聯(lián)想 AND price:1100":1},"facet_fields":{},"facet_dates":{},"facet_ranges":{}}} -------------------------------- 參數(shù) &facet=true &facet.query={!key=聯(lián)想}brand:聯(lián)想 AND price:1100 返回結(jié)果 "facet_counts":{"facet_queries":{"聯(lián)想":1},"facet_fields":{},"facet_dates":{},"facet_ranges":{}}}?從上面可以看出來,這樣可以讓字段名統(tǒng)一起來,方便我們拿到請求數(shù)據(jù)后,封裝成自己的對象
?
九)tag操作符和ex操作符
這個也非常的重要,看下應用場景,當查詢使用filter query 或者q的時候,如果filter query的字段正好是Facet字段,那么查詢結(jié)果往往被限制在某一個值內(nèi).
參考實例
&fq=price:[1000 TO 2000] &facet.field=price?返回結(jié)果
"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":{}}}? ? ? ?從返回的結(jié)果可以看到fq將查詢的結(jié)果集限制在了price 在1000 至 2000之間,其他范圍的統(tǒng)計沒有實際意義。
? ? 有些時候,用戶希望把結(jié)果限制在某一個范圍以內(nèi),又希望查看該范圍外的概況,像上述情況,用戶想把結(jié)果限制在(price)1000~2000之間,但是又想查看其他價格區(qū)間有多少產(chǎn)品。這個時候需要用到tag和ex操作符.tag就是把一個filter標記起來,ex(exclude)是在Facet的時候把標記過的filter排除在外.
參考實例
?
&fq={!tag=aa}price:[1000 TO 2000] &facet.field={!ex=aa}price?返回結(jié)果
?
"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":{}}}?這樣其它價格區(qū)間的統(tǒng)計信息就有意義了.
?
?
十)Facet 字段設(shè)計
一、Facet字段的要求
? ? ? ? Facet的字段必須被索引.一般來說該字段無需分詞,無需存儲.
? ? ? ? 無需分詞是因為該字段的值代表了一個整體概念,如電腦的品牌”聯(lián)想”代表了一個整體概念,如果拆成”聯(lián)”,”想”兩個字都不具有實際意義.另外該字段的值無需進行大小寫轉(zhuǎn)換等處理,保持其原貌即可.
? ? ? ? 無需存儲是因為一般而言用戶所關(guān)心的并不是該字段的具體值,而是作為對查詢結(jié)果進行分組的一種手段,用戶一般會沿著這個分組進一步深入搜索.
?
二、特殊情況
? ? ? ? ? 對于一般查詢而言,分詞和存儲都是必要的.比如CPU類型“Intel 酷睿2雙核 P7570”,拆分成“Intel”,“酷睿”,“P7570”這樣一些關(guān)鍵字并分別索引,可能提供更好的搜索體驗.但是如果將CPU作為Facet字段,最好不進行分詞.這樣就造成了矛盾,解決方法為,將CPU字段設(shè)置為不分詞不存儲,然后建立另外一個字段為它的COPY,對這個COPY的字段進行分詞和存儲.
<types><fieldType name="string" class="solr.StrField" omitNorms="true"/><fieldType name="tokened" class="solr.TextField" ><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"/>?
?
?官網(wǎng)API: ?http://wiki.apache.org/solr/SimpleFacetParameters?
?
轉(zhuǎn)載于:https://my.oschina.net/boltwu/blog/412865
總結(jié)
以上是生活随笔為你收集整理的Solr Facet 查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 那些曾经卖1万元的高端手机,现在只要50
- 下一篇: iPhone 用户反馈苹果 iOS 17