2008-08-29 71 views
15

假設我有一個叫做的字段,價格爲,這是Solr中的文檔,我有這個字段。我想要將各個方面作爲值的範圍(例如:0-100,100-500,500-1000等)。怎麼做?如何獲得solr結果中的分面範圍?

我可以事先指定範圍,但我也想知道是否可以根據文檔中的值自動計算範圍(比如5個值)?

回答

4

有可能是一個更好的Solr特定的答案,但我使用直Lucene,並且因爲你沒有得到太多的牽引力,我會採取刺。在那裏,我會創建一個包含原始QueryFilterFilteredQuery。然後我會得到感興趣領域的FieldCache。在篩選器的位集中枚舉匹配,並且對於每個匹配,您從字段緩存中獲取該字段的值,並將其添加到SortedSet。當你得到所有命中時,將該組的大小劃分爲你想要的範圍數(根據用戶界面球員,五到七是一個好數字),而不是單值約束,你的方面將會是一個範圍查詢,每個子集的下限和上限。

我推薦使用一些特殊的邏輯來處理少量的值;顯然,如果你只有四個不同的值,那麼嘗試使用5個範圍優化是沒有意義的。低於某個閾值(例如3 *您理想的範圍數),您只需顯示小平面而不是範圍。

14

要回答您的第一個問題,您可以使用通用構面查詢支持來獲取構面範圍。 Here的一個例子:

http://localhost:8983/solr/select?q=video&rows=0&facet=true&facet.query=price:[*+TO+500]&facet.query=price:[500+TO+*] 

至於你的第二個問題(自動提示面範圍),這還沒有實現。有人認爲,這種查詢最好在你的應用程序上實現,而不是讓Solr「猜測」最好的方面範圍。

以下是關於這個專題的一些討論:

+1

也許爲六年遲到了,但鏈接不再起作用。 – Bucket 2014-07-07 17:32:19

6

我已經計算出如何計算產品價格範圍的敏感動態構面。該解決方案涉及文檔的預處理和查詢結果的一些後處理,但它只需要一個查詢到Solr,甚至可以在舊版本的Solr上工作,如1.4。

輪價格上漲提交前

首先,提交文件之前,一輪上漲的價格到最近的「好圓面邊界」,並將其存儲在一個「rounded_price」字段。用戶喜歡他們的方面看起來像「250-500」而不是「247-483」,四捨五入也意味着你可以回到數百個價格方面而不是數百萬方面。隨着一些努力,下面的代碼可以推廣到任何規模的價格很好地輪:

public static decimal RoundPrice(decimal price) 
    { 
     if (price < 25) 
      return Math.Ceiling(price); 
     else if (price < 100) 
      return Math.Ceiling(price/5) * 5; 
     else if (price < 250) 
      return Math.Ceiling(price/10) * 10; 
     else if (price < 1000) 
      return Math.Ceiling(price/25) * 25; 
     else if (price < 2500) 
      return Math.Ceiling(price/100) * 100; 
     else if (price < 10000) 
      return Math.Ceiling(price/250) * 250; 
     else if (price < 25000) 
      return Math.Ceiling(price/1000) * 1000; 
     else if (price < 100000) 
      return Math.Ceiling(price/2500) * 2500; 
     else 
      return Math.Ceiling(price/5000) * 5000; 
    } 

允許價漲1,2,3,...,24,25,30,35,...,95100110 ,...,240,250,275,300,325,...,975,1000等等。

獲取有關圓的價格

二,提交查詢時,請求對價格圓潤按價格排列各個方面各個方面:facet.field=rounded_price。由於四捨五入,你最多可以得到幾百個方面。

合併相鄰面成更大的面

第三,你有結果之後,用戶希望看到的只有3到7面,甚至幾百個刻面。因此,相鄰面合併爲幾個大的方面(稱爲「段」),試圖讓每一段的文檔數量大致相等。下面相當複雜的代碼執行此,返回(開始,結束,計數)合適的元組執行範圍查詢。返回的將是正確的提供價格的計數被四捨五入到最近的邊界:通過選擇面

四,假設

public static List<Tuple<string, string, int>> CombinePriceFacets(int nSegments, ICollection<KeyValuePair<string, int>> prices) 
    { 
     var ranges = new List<Tuple<string, string, int>>(); 
     int productCount = prices.Sum(p => p.Value); 
     int productsRemaining = productCount; 
     if (nSegments < 2) 
      return ranges; 
     int segmentSize = productCount/nSegments; 
     string start = "*"; 
     string end = "0"; 
     int count = 0; 
     int totalCount = 0; 
     int segmentIdx = 1; 
     foreach (KeyValuePair<string, int> price in prices) 
     { 
      end = price.Key; 
      count += price.Value; 
      totalCount += price.Value; 
      productsRemaining -= price.Value; 
      if (totalCount >= segmentSize * segmentIdx) 
      { 
       ranges.Add(new Tuple<string, string, int>(start, end, count)); 
       start = end; 
       count = 0; 
       segmentIdx += 1; 
      } 
      if (segmentIdx == nSegments) 
      { 
       ranges.Add(new Tuple<string, string, int>(start, "*", count + productsRemaining)); 
       break; 
      } 
     } 
     return ranges; 
    } 

篩選結果(「250」,「500」,38)是其中一個結果部分。如果用戶選擇「$ 250至$ 500強」作爲一個過濾器,只需做一個篩選查詢fq=price:[250 TO 500]