如何基于Solr查询函数结果生成价格分面并实现过滤?
我有一个产品索引,每个产品对应不同店铺的价格字段,示例数据如下:
{ "id" : "p1", "name_s" : "Product 1", "description_s" : "The first product", "price_l1_d" : 19.99, "price_l2_d" : 20.00, "price_l3_d" : 20.99, "price_l4_d" : 19.99, "price_l5_d" : 25.00, "price_l6_d" : 18.00 }, { "id" : "p2", "name_s" : "Product 2", "description_s" : "The second product", "price_l1_d" : 12.99, "price_l2_d" : 15.00, "price_l3_d" : 13.49, "price_l4_d" : 14.00, "price_l5_d" : 12.50, "price_l6_d" : 16.00 }
我需要查询返回客户3个最近店铺中的最低价格,目前已能通过fl=min(price_l2_d, price_l4_d, price_l6_d)获取该值并排序,但想基于这个计算结果为每个文档生成「价格」分面——理想状态是展示并过滤出3个店铺中最低价格处于0-5、5-10、10-15等区间的所有产品。
我尝试把min(price_l2_d, price_l4_d, price_l6_d)作为facet.field使用,却收到「未定义字段」错误。由于最近3个店铺可能是任意价格字段组合(示例里是6个,实际超过200个),没法在索引阶段预生成这个值,有没有更优的解决方案?
1. 用Solr函数分面直接实现
这是最适配你场景的原生方案,不需要预定义字段,直接基于min函数做分面查询。通过facet.query指定每个价格区间的计算条件,示例请求如下:
q=*:* &fl=id,name_s,min(price_l2_d,price_l4_d,price_l6_d) as nearest_min_price &facet=true &facet.query=min(price_l2_d,price_l4_d,price_l6_d):[0 TO 5] &facet.query=min(price_l2_d,price_l4_d,price_l6_d):[5 TO 10] &facet.query=min(price_l2_d,price_l4_d,price_l6_d):[10 TO 15] &facet.query=min(price_l2_d,price_l4_d,price_l6_d):[15 TO 20] &facet.query=min(price_l2_d,price_l4_d,price_l6_d):[20 TO *]
每次查询只要替换min函数里的店铺价格字段列表就行,Solr会直接计算每个区间内的匹配文档数,同时返回每个产品的最低价格。
2. 应用层后处理分面(备选)
如果需要更灵活的区间逻辑,可以先通过fl把计算出的最低价格作为伪字段返回,拿到所有文档的nearest_min_price值后,在应用层面自行统计各区间的数量并实现过滤。但这种方式在数据量较大时性能不如原生函数分面,适合小规模数据集。
关键注意点
因为店铺组合是动态的,预生成所有可能的组合字段完全不现实(200个店铺的组合数是天文数字),必须坚持在查询阶段计算。函数分面是Solr原生支持的高效方案,不需要改造现有索引,完全适配你的动态场景。
内容的提问来源于stack exchange,提问作者Jamie Bartlett

