2008-08-29 25 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]