您的位置:首页 > 其它

solr 个性化打分

2016-06-14 21:32 190 查看

背景

搜索排序怎么排呢,如果还是想着怎么改similarity或者SchemaSimilarityFactory就范围太小了,similarity只能提供一个文本相关性得分,不管你怎么boost去调整,最后你会发现这他妈根本不是你想要的打分逻辑,tf, idf, lengthnorm, coord,boost,甚至还涉及到lucene-core 下SmallFloat的精度问题,一团乱麻。

方案

可以扩展solr的CustomScoreQuery,例如:

public class NiuniuQuery extends CustomScoreQuery {

public NiuniuQuery(Query subQuery) {
super(subQuery);
}

@Override
protected CustomScoreProvider getCustomScoreProvider(
AtomicReaderContext context) throws IOException{
return new NiuniuScoreProvider(context, user_info);
}
}


然后在NiuniuScoreProvider(扩展自solr的CustomScoreProvider模块)中实现打分逻辑即可,上层可以把用户相关的参数带进来,这样在NiuniuScoreProvider就可以进行个性化或者业务逻辑相关的打分计算了,sample代码如下:

@Override
public float customScore(int doc, float subQueryScore,
float[] valSrcScores) throws IOException {
// Method is called for every
// matching document of the subQuery
// subQueryScore就是使用Similarity得到的分数
Document document = context.reader().document(doc);
String timestamp = document.get("updated_at");
String vip = document.get("user_vip_level");
String deposit = document.get("user_deposit");

float niuniu_score = niuniuFeature(timestamp, vip, deposit);
//System.out.println("Niuniu Custom Score is: " + Float.toString(niuniu_score));
return subQueryScore + niuniu_score;
}


不用担心,Similarity计算出来的文本相关性分数就是customScore方法中的subQueryScore,至于用不用就随便你了。但是看这段代码的注释,是说每view一个document,都会调一次这个逻辑,那么假如我手贱,查了个*,即所有文档,那么就会对所有文档走这个算分逻辑,这个对于搜索时间影响非常非常大,甚至要1s才能返回结果。

当前情况是我们的数据量较小,10w级别,不搜索* (即所有文档)的话每个query基本上顶多也只有1w条,所以其实对于每个满足条件的文档,走CustomScoreProvider也没有太大问题,但是为了尽可能的提高效率,我们还需要把很多的计算逻辑在线下建索引的时候就计算好,把它作为一个字段,线上直接使用字段去加分或者排序即可,省掉了复杂的算分逻辑。

想到之前在阿里做个性化排序的框架战马,这个模块就是在精排阶段在线上调用模型来干预排序,但是如果对淘宝数亿级别的商品做个性化那就是纯傻逼。所以他们首先会进行粗排,即把文本、类目等相关性分数最靠前的几千条结果保留,让这些结果去精排进行算分,这样就可以极大的降低精排的时间成本。

这个模块应该放在collector收集完较大数量符合条件的结果以后,再对所有的候选结果(粗排结果)来进行,这一步在solr中可以放在SolrIndexSearch中进行(不能放在QueryComponent中进行,原因见下:

WARNING: Any DocSet returned from SolrIndexSearcher should not be modified as it may have been retrieved from a cache and could be shared.

即搜索结果从SolrIndexSearcher返回不能修改,具体和缓存相关,后续会关注一下缓存的机制,有几套缓存机制,但是细节还不清楚~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息