solr实现药品采购价动态排序
?药品名称
供应商ID
云南白药
X
10
云南白药
Y
9
云南白药
Z
11
? ? ? ?也就是说,用户看到的采购价这一列在索引中并不存在,而是根据批发商提供的三个不同价格加上用户面对每个批发商的采购权限来从三个价格中选取一个作为采购价提供给前台,展示给用户查看,购买.
这个变态的需求折磨了我2个礼拜,一次次实验一次次失败.
?
第一个想到的解决方案是这样的
? ? ? ?修改lucene底层对double类型排序的源码.
? ? ? ?org.apache.lucene.search.FieldComparator.DoubleComparator<T>
? ? ? ?在这个类中,可以取到要排序的这一条记录的每一列的值.我就突然奇想,这个方法虽然是对某一列排序,但是可以改变其排序方法内部实现,根据一定的算法规则,从三个价格中动态的选取一个进行排序,后来经过本地测试也是可行的.但是在项目在真正运用的时候发现了问题.搭建的solr环境大概是有solr服务端,搜索应用程序通过java开发,运用solrj与solr服务端进行交互.设想的是当用户登录的后,取得用户与供应商之间的采购折扣关系字符串,设置在ThreadLocal中,传入到solr服务端的lucene排序接口中.但是lucene底层始终拿不到设置的值.经过思考,我认为是solrj通过构建一个http查询,发送到solr服务端,ThreadLocal中的值自然也就丢掉了.
? ? ? ?没办法又回到起点,从新找突破口想办法.一直在网上找solr动态排序相关的文章,但是感觉都没有启发.偶然间看到了这篇文章http://www.oschina.net/question/111391_18124?受到了很大的启发.按照这种思路,我自己琢磨着自定义一个函数,来满足业务需求.
? ? ??
package org.apache.solr.search;import org.apache.lucene.queries.function.FunctionValues;import org.apache.lucene.queries.function.ValueSource;import org.apache.lucene.queries.function.valuesource.MultiFloatFunction;import org.apache.lucene.queries.function.valuesource.PriceService;public class SortPriceFunction extends MultiFloatFunction {private String priceSF;public SortPriceFunction(ValueSource[] sources) {super(sources);}public SortPriceFunction(ValueSource[] sources, String priceSF) {super(sources);this.priceSF = priceSF;}/** * 动态排序实现 */@Overrideprotected float func(int doc, FunctionValues[] vals) {//初始化一个排序算法类,根据用户与供应商之间的关系,来决定选取哪个价格PriceService service = new PriceService(this.priceSF);String gcpFileName = service.getPriceField(vals[3].intVal(doc),vals[4].intVal(doc),vals[5].intVal(doc));float result;if (null == gcpFileName) {result = vals[6].floatVal(doc);} else if ("gcp_1".equals(gcpFileName)) {result = vals[0].floatVal(doc);} else if ("gcp_2".equals(gcpFileName)) {result = vals[1].floatVal(doc);} else {result = vals[2].floatVal(doc);}return result;}@Overrideprotected String name() {return "price";}}
?在org.apache.solr.search.ValueSourceParser中添加如下代码
addParser("price", new ValueSourceParser() {public ValueSource parse(FunctionQParser fp) throws SyntaxError {String priceSF = fp.getReq().getParams().get("priceSF");List<ValueSource> sources = fp.parseValueSourceList();return new SortPriceFunction(sources.toArray(new ValueSource[sources.size()]),priceSF);}});
?在搜索应用中的代码如下
//将用户与供应商之间的关系字符串作为参数传入solr服务端query.setParam("priceSF", priceSF);//调用自定义的price函数进行排序query.addSort("price(grice1,grice2,grice3,算法需要的业务字段,算法需要的业务字段,算法需要的业务字段,算法需要的业务字段)", ORDER.asc);
?
这样一来,就实现了针对每一天商品,动态取三个价格中的某一个进行动态排序.
?不善描述,以上所述,如有疑问请指出,欢迎交流!