solr入门之自定义排序之构建自己的权重计算方法及相应的排序字段

时间:2022-07-17 19:55:03
需求:

1、需求:调整排序算法改为综合得分排名

2、规则:

①搜索方式:先过滤,后排序

②搜索字段:用户昵称

③匹配方式:分词完全匹配

④排序按照综合得分高低进行排序展示

综合得分=

达人得分(权重:单独计算)

+粉丝数得分(权重:75%

+基础得分(权重:25%

a.达人得分

在搜索结果中置顶展示,其中优先开通美店达人

b.粉丝数得分

粉丝数越多,权重越高(需要开发相应算法计算相对值)

c.基础得分

上传过头像、修改过签名(不重复计算)


实现思路: 设置最大权重值,每个用户按照各自条件计算相应的得分数(最小最大规范化也叫离差标准化) 是达人时再加上最大权重(置顶效果)当达人有美店时再次加上最大权重(置顶中的置顶) 为什么可以这么做?因为要求先过滤后进行排序,既当符合搜索条件后,排序再单独进行计算 完全不需要考虑查询过程中的匹配而产生的权重.


实现:



/**
* Copyright (C) 2015-2020 gome meixin_search Inc.All Rights Reserved.
*
* FileName:UserWeightCalculator.java
*
* Description:简要描述本文件的内容
*
* History:
* 版本号 作者 日期 简要介绍相关操作
* 1.0 liuyuxin 2016年4月13日
*
*/
package cn.com.mx.gome.flash.similarity;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.com.mx.gome.flash.constant.Const;
import cn.com.mx.gome.flash.entity.EcpUser;
import cn.com.mx.gome.flash.load.ConfigCenter;
import cn.com.mx.gome.flash.util.PropUtil;
import cn.com.mx.gome.search.core.weight.WeightAlgorithm;
import cn.com.mx.gome.search.core.weight.WeightCalculator;

/**
*
*
*/
@Component("userWeightCalculator")
public class UserWeightCalculator implements WeightCalculator<EcpUser>, InitializingBean {

private static final Logger logger = LoggerFactory.getLogger(UserWeightCalculator.class);

private String defaultUserPic = null;

/**
* 假设的权重总分,最大粉丝数;这俩数变了,得重建索引
*/
public Double maxUserScore = PropUtil.getInstance().getDouble(Const.WEIGHT_USER_MAX, 100000),
maxFollowerCount = PropUtil.getInstance().getDouble(Const.WEIGHT_USER_FOLLOWER_MAX, 5000);

/*
* (non-Javadoc)
*
* @see
* cn.com.mx.gome.search.core.weight.WeightCalculator#calculate(java.lang
* .Object)
*/
@Override
public Double calculate(EcpUser t) {
double score = 0;
boolean hasPic = t.getUserPic() != null
&& !(t.getUserPic().equals(defaultUserPic) && !(t.getUserPic().equalsIgnoreCase("null")));// 有头像
boolean hasUserSign = t.getUser_sign() != null && t.getUser_sign().length() > 0
&& !(t.getUser_sign().equalsIgnoreCase("null"));// 有签名
// 签名和头像占25%权重
if (hasPic)
score += (maxUserScore * 0.25) / 2;
if (hasUserSign)
score += (maxUserScore * 0.25) / 2;

// 粉丝数,占75%权重
if (t.getFollowerCount() != null && t.getFollowerCount() > 0)
score += WeightAlgorithm.normalization(t.getFollowerCount().doubleValue(), 0.0, maxFollowerCount, 0.0,
maxUserScore * 0.75);

boolean isVIP = t.getStatus() == Const.USER_STATUS_V;
boolean hasShop = t.getType() == Const.USER_TYPE_HASSHOP;
// 达人置顶
if (isVIP) {
score += maxUserScore;
// 优先美店
if (hasShop)
score += maxUserScore;
}
t.setWeight(score);
return score;
}

/*
* (non-Javadoc)
*
* @see
* org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
defaultUserPic = configCenter.get("user.logo.default");
logger.info("default user pic path= , {}", defaultUserPic);
}

@Autowired
private ConfigCenter configCenter;
}


算法:


/**
* Copyright (C) 2015-2020 gome meixin_search Inc.All Rights Reserved.
*
* FileName:WeightAlgorithm.java
*
* Description:简要描述本文件的内容
*
* History:
* 版本号 作者 日期 简要介绍相关操作
* 1.0
*
*/
package cn.com.mx.gome.search.core.weight;

/**
* @author
*
*/
public class WeightAlgorithm {
/**
*
* @描述:最小最大规范化也叫离差标准化 ,可以对原始数据进行线性变换 ; 假定min和max是最小值和最大值,
* v是该区间中的一个值,将其映射到新的区间[newMin, newMax]中为v' 则有: v' =
* (v-Min)/(max-min)*(newMax-newMin)+newMin
* 这种方法有一个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义。
* @param v
* 做标准化的样本数据
* @param min
* 样本数据最小值
* @param max
* 样本数据最大值
* @param newMin
* 新的映射区间最小值
* @param newMax
* 新的映射区间最大值
* @return
* @return double
* @exception
* @createTime:2016年4月8日
* @author: liuyuxin
*/
public static Double normalization(Double v, Double min, Double max, Double newMin, Double newMax) {
return (v - min) / (max - min) * (newMax - newMin) + newMin;
}

}