假设我在Solr中有一个名为price的字段,我将该字段刻面.我希望将facet作为值的范围(例如:0-100,100-500,500-1000等).怎么做?
我可以预先指定范围,但我也想知道是否可以根据文档中的值自动计算范围(比如5个值)?
Mau*_*fer 14
要回答第一个问题,可以使用通用构面查询支持来获取构面范围.这是一个例子:
http://localhost:8983/solr/select?q=video&rows=0&facet=true&facet.query=price:[*+TO+500]&facet.query=price:[500+TO+*]
Run Code Online (Sandbox Code Playgroud)
至于你的第二个问题(自动建议方面范围),这还没有实现.有些人认为,这种查询最好在您的应用程序上实现,而不是让Solr"猜测"最佳方面范围.
以下是关于该主题的一些讨论:
我已经研究了如何计算产品价格范围的合理动态方面.该解决方案涉及一些文档的预处理和一些查询结果的后处理,但它只需要一个查询到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;
}
Run Code Online (Sandbox Code Playgroud)
允许的价格为1,2,3,......,24,25,30,35,......,95,100,110,......,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;
}
Run Code Online (Sandbox Code Playgroud)
第四,假设("250","500",38)是结果段之一.如果用户选择"$ 250到$ 500"作为过滤器,只需执行过滤查询fq=price:[250 TO 500]
很可能有更好的特定于 Solr 的答案,但我直接使用 Lucene,并且由于您没有得到太多关注,所以我会尝试一下。在那里,我将创建一个填充 aFilter并FilteredQuery包装原始Query. 然后我会得到一个FieldCache感兴趣的领域。枚举过滤器位集中的命中,对于每个命中,您从字段缓存中获取字段的值,并将其添加到 SortedSet 中。当您获得所有命中后,将集合的大小划分为您想要的范围数量(根据用户界面人员的说法,五到七是一个很好的数字),而不是单值约束,您的方面将是一个范围查询,其中包含每个子集的下限和上限。
我建议对少量值使用一些特殊情况逻辑;显然,如果您只有四个不同的值,那么尝试对它们进行 5 个范围细化是没有意义的。低于某个阈值(例如 3*您的理想范围数),您只需正常显示方面而不是范围。
| 归档时间: |
|
| 查看次数: |
26397 次 |
| 最近记录: |