- Solr權(quán)威指南(下卷)
- 蘭小偉
- 1802字
- 2019-01-03 15:33:40
11.3 Pivot Facet
在第6章,我們已經(jīng)學(xué)習(xí)了Solr中的Facet查詢,包括Query Facet(基于一個(gè)查詢進(jìn)行Facet)、Facet Filter(結(jié)合Filter Query來過濾Facet)、Range Facet(實(shí)現(xiàn)Facet區(qū)間范圍查詢統(tǒng)計(jì))、Field Facet(基于域進(jìn)行Facet)等。但是有時(shí)候,實(shí)現(xiàn)嵌套Facet會(huì)很非常有用,這就好比傳統(tǒng)關(guān)系型數(shù)據(jù)庫中,我們可以group by a, b對(duì)a和b兩個(gè)字段進(jìn)行分組統(tǒng)計(jì)是類似的。Solr支持這種嵌套Facet來實(shí)現(xiàn)類似SQL里的同時(shí)按多個(gè)字段group by的功能:Pivot Facet。
Pivot Facet支持多某個(gè)域進(jìn)行Facet。比如你的關(guān)于“飯店”的索引數(shù)據(jù)中包含了state、city、rating這3個(gè)域,rating域表示飯店的星級(jí),用1~5顆星星表示。當(dāng)想要統(tǒng)計(jì)各個(gè)城市各個(gè)州下4~5星級(jí)酒店總數(shù)時(shí),就可以使用Pivot Facet功能來實(shí)現(xiàn)類似這種需求。
首先還是跟之前的章節(jié)一樣,請(qǐng)根據(jù)隨書源碼提供的文件創(chuàng)建"pivotfaceting" Core,并執(zhí)行IndexPivotFacet測(cè)試類導(dǎo)入測(cè)試數(shù)據(jù)到"pivotfaceting" Core中,為我們接下來的查詢測(cè)試做好準(zhǔn)備。
假定此時(shí)你已經(jīng)成功導(dǎo)入了測(cè)試數(shù)據(jù),那么請(qǐng)隨我一起執(zhí)行下面這個(gè)Facet查詢示例:
http://localhost:8080/solr/pivotfaceting/select? q=*:*& fq=rating:[4 TO 5]&facet=true&facet.limit=3& facet.pivot.mincount=1&facet.pivot=state, city, rating
返回的結(jié)果集部分如下所示:
acet_pivot":{ "state, city, rating":[{ "field":"state", "value":"GA", "count":4, "pivot":[{ "field":"city", "value":"Atlanta", "count":4, "pivot":[{ "field":"rating", "value":4, "count":2}, { "field":"rating", "value":5, "count":2}]}]},
以上的查詢示例演示了Pivot Facet的3級(jí)嵌套,通過facet.pivot參數(shù)定義了3個(gè)使用逗號(hào)分隔的域,不像我們第6章里學(xué)習(xí)的根據(jù)單個(gè)域進(jìn)行Facet只會(huì)單個(gè)Facet統(tǒng)計(jì)值,Pivot Facet除了會(huì)返回當(dāng)前域上的Facet統(tǒng)計(jì)值,還會(huì)繼續(xù)按照下一個(gè)域?qū)Ξ?dāng)前域的Facet統(tǒng)計(jì)值進(jìn)行分組細(xì)分統(tǒng)計(jì),你可以這樣一直嵌套下去。這種嵌套Facet在實(shí)際中很有用,比如當(dāng)你在搜索“手機(jī)”,你首先關(guān)心的是手機(jī)品牌,如果網(wǎng)站將手機(jī)數(shù)據(jù)按照品牌分組,這樣就能快速幫你過濾掉其他不喜歡的品牌的手機(jī)數(shù)據(jù),緊接著你可能關(guān)心的是手機(jī)的價(jià)格,因此此時(shí)可以在原來品牌手機(jī)的基礎(chǔ)再按照不同價(jià)格區(qū)間對(duì)手機(jī)進(jìn)行分類統(tǒng)計(jì),比如你購買手機(jī)的預(yù)算是5000元左右,那么不符合這個(gè)價(jià)格區(qū)間范圍的手機(jī)又被過濾掉,下一步你可以會(huì)挑選手機(jī)顏色,就這樣層層疊加多個(gè)維度對(duì)手機(jī)數(shù)據(jù)進(jìn)行分類統(tǒng)計(jì)在實(shí)際項(xiàng)目中很常見也很有用。這跟SQL里的Group by多個(gè)字段的特性有種似曾相識(shí)的感覺。
假如有這樣一個(gè)需求,你想要統(tǒng)計(jì)每個(gè)班級(jí)下60~70分、70~80分、80~90分、90~100分各個(gè)分?jǐn)?shù)段之間的人數(shù)。這里的分?jǐn)?shù)區(qū)間查詢可以使用我們前面學(xué)習(xí)過的facet. range來實(shí)現(xiàn),統(tǒng)計(jì)每個(gè)班級(jí)顯然是根據(jù)班級(jí)進(jìn)行分組,這里班級(jí)和分?jǐn)?shù)區(qū)間相當(dāng)于是分組統(tǒng)計(jì)的兩個(gè)維度即Facet,現(xiàn)在要求在班級(jí)這個(gè)維度再疊加一個(gè)分?jǐn)?shù)區(qū)間維度進(jìn)行統(tǒng)計(jì),此時(shí)我們需要使用Pivot Facet來實(shí)現(xiàn),查詢示例如下所示:
http://localhost:8080/solr/yourcore/select? q=*:*& facet=true&facet.range={! tag=grade}fenshu& f.fenshu.facet.range.start=60&f.fenshu.facet.range.end=100& f.fenshu.facet.range.gap=10& facet.pivot={! range=grade}classes
這里的classes表示班級(jí)Field, fenshu表示分?jǐn)?shù)Field,我們先在外面按照分?jǐn)?shù)域定義了facet.range區(qū)間范圍查詢,然后我們通過{! range=grade}語法在facet.pivot上疊加了區(qū)間范圍這個(gè)維度進(jìn)行統(tǒng)計(jì),這樣就實(shí)現(xiàn)了我們的需求。同理你還可以使用facet.query并將facet. query作為一個(gè)2級(jí)維度疊加嵌套到facet.pivot所在域即classes域上,比如你想要統(tǒng)計(jì)每個(gè)班級(jí)姓“杜”的有多少人,那么你可以這樣查詢實(shí)現(xiàn),示例如下所示:
http://localhost:8080/solr/yourcore/select? q=*:*& facet=true&facet.query={! tag=nameFilter}stuName:杜*& facet.pivot={! query=nameFilter}classes
當(dāng)然你可以將query和range在pivot facet中結(jié)合在一起,比如:
facet.pivot={! range=grade query=nameFilter}classes
但是需要注意的是,上面的grade和nameFilter是同級(jí)Facet,即總共只有classes和grade/nameFilter兩級(jí)Facet,也就是說它們是分別在classes域Facet之后的基礎(chǔ)上再Facet統(tǒng)計(jì)。如果你想要實(shí)現(xiàn)兩個(gè)Facet Query之間的Facet嵌套,即將一個(gè)Facet Query作為一個(gè)維度進(jìn)行Facet統(tǒng)計(jì),然后在其基礎(chǔ)之上再定義一個(gè)Facet Query作為2級(jí)維度繼續(xù)Facet統(tǒng)計(jì),很遺憾,Solr暫時(shí)還不支持這種任意兩個(gè)Query定義的Facet之間的嵌套統(tǒng)計(jì)查詢。雖然Pivot Facet是用來設(shè)計(jì)解決多維度疊加統(tǒng)計(jì)問題的,但是Pivot Facet目前只支持先按照指定的域作為第一級(jí)維度進(jìn)行Facet統(tǒng)計(jì),然后二級(jí)維度可以繼續(xù)是一個(gè)域,也可以是任意Query。
Pivot Facet其實(shí)還有一定的性能約束。因?yàn)镻ivot Facet需要將一個(gè)Facet再細(xì)分為多個(gè)子Facet,與單獨(dú)執(zhí)行每個(gè)Facet統(tǒng)計(jì)相比,為每個(gè)Facet計(jì)算子層級(jí)的Facet這需要額外的計(jì)算執(zhí)行開銷。通常我們最關(guān)心的是Pivot Facet對(duì)大數(shù)據(jù)量進(jìn)行統(tǒng)計(jì)時(shí)性能如何。比如我們的第一個(gè)Pivot Facet中我們按照state、city、rating這3個(gè)Facet進(jìn)行統(tǒng)計(jì),它們依次表示了3個(gè)層級(jí)的Facet,一級(jí)一級(jí)地將Facet細(xì)分下去,所以我們得到3×3×3 = 27個(gè)Facet,如果每個(gè)Facet下有100或1000個(gè)甚至10000個(gè)唯一值的話,那返回的結(jié)果集將會(huì)非常大。而且Pivot Facet返回的結(jié)果集數(shù)據(jù)比普通的Facet更冗長(zhǎng),很容易就使得返回的結(jié)果集大小達(dá)到幾MB,當(dāng)然你可以通過facet.limit參數(shù)來限制每個(gè)Facet內(nèi)返回的記錄條數(shù)來控制返回的結(jié)果集字節(jié)大小。而假如你的需求確實(shí)需要每組返回Top 100或Top 1000,那么你的Java堆內(nèi)存可能會(huì)撐爆,內(nèi)存會(huì)被瞬間消耗掉,其他查詢自然無法充分利用緩存,查詢速度也會(huì)隨之下降,甚至出現(xiàn)響應(yīng)卡頓。鑒于以上原因,當(dāng)你考慮需要根據(jù)幾個(gè)域進(jìn)行嵌套統(tǒng)計(jì)或者每個(gè)Facet下最多返回多少個(gè)值時(shí),你需要格外謹(jǐn)慎,心中要清楚可能會(huì)導(dǎo)致的后果。
- UNIX編程藝術(shù)
- 基于粒計(jì)算模型的圖像處理
- 少年輕松趣編程:用Scratch創(chuàng)作自己的小游戲
- PyTorch自然語言處理入門與實(shí)戰(zhàn)
- KnockoutJS Starter
- Hadoop 2.X HDFS源碼剖析
- PyQt編程快速上手
- ArcPy and ArcGIS(Second Edition)
- Enterprise Application Architecture with .NET Core
- jBPM6 Developer Guide
- Building E-Commerce Solutions with WooCommerce(Second Edition)
- C++面向?qū)ο蟪绦蛟O(shè)計(jì)教程
- Alfresco for Administrators
- C#程序開發(fā)教程
- 精通Spring MVC 4