|
@@ -12,14 +12,13 @@ import java.util.*;
|
|
|
public class ProfileRecommendService {
|
|
public class ProfileRecommendService {
|
|
|
|
|
|
|
|
@Resource private MemberProfileDimensionMapper profileDimMapper;
|
|
@Resource private MemberProfileDimensionMapper profileDimMapper;
|
|
|
- @Resource private ArticleDimensionMappingMapper articleDimMapper;
|
|
|
|
|
- @Resource private ActivityDimensionMappingMapper activityDimMapper;
|
|
|
|
|
- @Resource private ProductDimensionMappingMapper productDimMapper;
|
|
|
|
|
@Resource private AiQSessionMapper sessionMapper;
|
|
@Resource private AiQSessionMapper sessionMapper;
|
|
|
|
|
+ @Resource private DimensionWeightService dimensionWeightService;
|
|
|
@Resource private ArticleMapper articleMapper;
|
|
@Resource private ArticleMapper articleMapper;
|
|
|
@Resource private ActivityMapper activityMapper;
|
|
@Resource private ActivityMapper activityMapper;
|
|
|
@Resource private ProductMapper productMapper;
|
|
@Resource private ProductMapper productMapper;
|
|
|
@Resource private RecommendationLogMapper recommendationLogMapper;
|
|
@Resource private RecommendationLogMapper recommendationLogMapper;
|
|
|
|
|
+ @Resource private ProductDimensionMappingMapper productDimMapper;
|
|
|
|
|
|
|
|
public Map<String, Object> recommend(Long memberId, List<String> types, int limit) {
|
|
public Map<String, Object> recommend(Long memberId, List<String> types, int limit) {
|
|
|
Long sessionId = getLatestFinishedSession(memberId);
|
|
Long sessionId = getLatestFinishedSession(memberId);
|
|
@@ -48,7 +47,7 @@ public class ProfileRecommendService {
|
|
|
for (ItemScore item : items) {
|
|
for (ItemScore item : items) {
|
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
|
m.put("id", item.id);
|
|
m.put("id", item.id);
|
|
|
- m.put("type", type);
|
|
|
|
|
|
|
+ m.put("type", item.type);
|
|
|
m.put("title", item.title);
|
|
m.put("title", item.title);
|
|
|
m.put("summary", item.summary);
|
|
m.put("summary", item.summary);
|
|
|
m.put("coverImage", item.coverImage);
|
|
m.put("coverImage", item.coverImage);
|
|
@@ -88,46 +87,47 @@ public class ProfileRecommendService {
|
|
|
|
|
|
|
|
if ("product".equals(type)) {
|
|
if ("product".equals(type)) {
|
|
|
List<ProductDimensionMapping> mappings = productDimMapper.selectList(
|
|
List<ProductDimensionMapping> mappings = productDimMapper.selectList(
|
|
|
- new LambdaQueryWrapper<ProductDimensionMapping>()
|
|
|
|
|
- .eq(ProductDimensionMapping::getEnabled, 1));
|
|
|
|
|
|
|
+ new LambdaQueryWrapper<ProductDimensionMapping>().eq(ProductDimensionMapping::getEnabled, 1));
|
|
|
Map<Long, Double> scores = new HashMap<>();
|
|
Map<Long, Double> scores = new HashMap<>();
|
|
|
for (ProductDimensionMapping m : mappings) {
|
|
for (ProductDimensionMapping m : mappings) {
|
|
|
- double dimScore = 0;
|
|
|
|
|
for (MemberProfileDimension d : userDims) {
|
|
for (MemberProfileDimension d : userDims) {
|
|
|
if (d.getDimensionCode().equals(m.getDimensionCode())) {
|
|
if (d.getDimensionCode().equals(m.getDimensionCode())) {
|
|
|
- dimScore += d.getScore() * m.getMatchScore();
|
|
|
|
|
|
|
+ double base = (d.getScore() * m.getMatchScore()) / totalProfileScore;
|
|
|
|
|
+ double finalScore = base + (needCodes.contains(m.getDimensionCode()) ? 20 : 0);
|
|
|
|
|
+ scores.merge(m.getProductId(), finalScore, Double::sum);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- if (dimScore > 0) {
|
|
|
|
|
- double base = dimScore / totalProfileScore;
|
|
|
|
|
- boolean isNeed = needCodes.contains(m.getDimensionCode());
|
|
|
|
|
- double finalScore = base + (isNeed ? 20 : 0);
|
|
|
|
|
- scores.merge(m.getProductId(), finalScore, Double::sum);
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
scores.forEach((pid, score) -> {
|
|
scores.forEach((pid, score) -> {
|
|
|
Product p = productMapper.selectById(pid);
|
|
Product p = productMapper.selectById(pid);
|
|
|
if (p != null) items.add(new ItemScore(pid, "product", p.getName(),
|
|
if (p != null) items.add(new ItemScore(pid, "product", p.getName(),
|
|
|
p.getDescription(), p.getCoverImage(), score, "高匹配"));
|
|
p.getDescription(), p.getCoverImage(), score, "高匹配"));
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
} else if ("article".equals(type)) {
|
|
} else if ("article".equals(type)) {
|
|
|
- List<ArticleDimensionMapping> mappings = articleDimMapper.selectList(
|
|
|
|
|
- new LambdaQueryWrapper<ArticleDimensionMapping>());
|
|
|
|
|
Map<Long, Double> scores = new HashMap<>();
|
|
Map<Long, Double> scores = new HashMap<>();
|
|
|
- for (ArticleDimensionMapping m : mappings) {
|
|
|
|
|
|
|
+ List<Article> articles = articleMapper.selectList(null);
|
|
|
|
|
+ for (Article a : articles) {
|
|
|
|
|
+ List<DimensionWeight> dw = dimensionWeightService.getByTarget("article", a.getId());
|
|
|
double dimScore = 0;
|
|
double dimScore = 0;
|
|
|
- for (MemberProfileDimension d : userDims) {
|
|
|
|
|
- if (d.getDimensionCode().equals(m.getDimensionCode())) {
|
|
|
|
|
- dimScore += d.getScore() * m.getMatchScore();
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ for (DimensionWeight w : dw) {
|
|
|
|
|
+ if (!Boolean.TRUE.equals(w.getEnabled())) continue;
|
|
|
|
|
+ for (MemberProfileDimension d : userDims) {
|
|
|
|
|
+ if (d.getDimensionCode().equals(w.getDimension())) {
|
|
|
|
|
+ dimScore += d.getScore() * w.getWeight();
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if (dimScore > 0) {
|
|
if (dimScore > 0) {
|
|
|
double base = dimScore / totalProfileScore;
|
|
double base = dimScore / totalProfileScore;
|
|
|
- boolean isNeed = needCodes.contains(m.getDimensionCode());
|
|
|
|
|
- double finalScore = base + (isNeed ? 20 : 0);
|
|
|
|
|
- scores.merge(m.getArticleId(), finalScore, Double::sum);
|
|
|
|
|
|
|
+ long matchedNeed = 0;
|
|
|
|
|
+ for (DimensionWeight w : dw) {
|
|
|
|
|
+ if (Boolean.TRUE.equals(w.getEnabled()) && needCodes.contains(w.getDimension())) matchedNeed++;
|
|
|
|
|
+ }
|
|
|
|
|
+ double finalScore = base + (20.0 * matchedNeed / Math.max(dw.size(), 1));
|
|
|
|
|
+ scores.merge(a.getId(), finalScore, Double::sum);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
scores.forEach((aid, score) -> {
|
|
scores.forEach((aid, score) -> {
|
|
@@ -135,23 +135,30 @@ public class ProfileRecommendService {
|
|
|
if (a != null) items.add(new ItemScore(aid, "article", a.getTitle(),
|
|
if (a != null) items.add(new ItemScore(aid, "article", a.getTitle(),
|
|
|
a.getSummary(), a.getCoverImage(), score, "高匹配"));
|
|
a.getSummary(), a.getCoverImage(), score, "高匹配"));
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
} else if ("activity".equals(type)) {
|
|
} else if ("activity".equals(type)) {
|
|
|
- List<ActivityDimensionMapping> mappings = activityDimMapper.selectList(
|
|
|
|
|
- new LambdaQueryWrapper<ActivityDimensionMapping>());
|
|
|
|
|
Map<Long, Double> scores = new HashMap<>();
|
|
Map<Long, Double> scores = new HashMap<>();
|
|
|
- for (ActivityDimensionMapping m : mappings) {
|
|
|
|
|
|
|
+ List<Activity> activities = activityMapper.selectList(null);
|
|
|
|
|
+ for (Activity act : activities) {
|
|
|
|
|
+ List<DimensionWeight> dw = dimensionWeightService.getByTarget("activity", act.getId());
|
|
|
double dimScore = 0;
|
|
double dimScore = 0;
|
|
|
- for (MemberProfileDimension d : userDims) {
|
|
|
|
|
- if (d.getDimensionCode().equals(m.getDimensionCode())) {
|
|
|
|
|
- dimScore += d.getScore() * m.getMatchScore();
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ for (DimensionWeight w : dw) {
|
|
|
|
|
+ if (!Boolean.TRUE.equals(w.getEnabled())) continue;
|
|
|
|
|
+ for (MemberProfileDimension d : userDims) {
|
|
|
|
|
+ if (d.getDimensionCode().equals(w.getDimension())) {
|
|
|
|
|
+ dimScore += d.getScore() * w.getWeight();
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if (dimScore > 0) {
|
|
if (dimScore > 0) {
|
|
|
double base = dimScore / totalProfileScore;
|
|
double base = dimScore / totalProfileScore;
|
|
|
- boolean isNeed = needCodes.contains(m.getDimensionCode());
|
|
|
|
|
- double finalScore = base + (isNeed ? 20 : 0);
|
|
|
|
|
- scores.merge(m.getActivityId(), finalScore, Double::sum);
|
|
|
|
|
|
|
+ long matchedNeed = 0;
|
|
|
|
|
+ for (DimensionWeight w : dw) {
|
|
|
|
|
+ if (Boolean.TRUE.equals(w.getEnabled()) && needCodes.contains(w.getDimension())) matchedNeed++;
|
|
|
|
|
+ }
|
|
|
|
|
+ double finalScore = base + (20.0 * matchedNeed / Math.max(dw.size(), 1));
|
|
|
|
|
+ scores.merge(act.getId(), finalScore, Double::sum);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
scores.forEach((actId, score) -> {
|
|
scores.forEach((actId, score) -> {
|