Showing
9 changed files
with
317 additions
and
311 deletions
@@ -28,7 +28,7 @@ public class RecommendBrandAggregation extends AbstractAggregation { | @@ -28,7 +28,7 @@ public class RecommendBrandAggregation extends AbstractAggregation { | ||
28 | this.simpleFieldAggs = new ArrayList<SimpleFieldAgg>(); | 28 | this.simpleFieldAggs = new ArrayList<SimpleFieldAgg>(); |
29 | simpleFieldAggs.add(new SimpleFieldAgg(aggName(), ProductIndexEsField.brandId, 300)); | 29 | simpleFieldAggs.add(new SimpleFieldAgg(aggName(), ProductIndexEsField.brandId, 300)); |
30 | // 构造TopHitOrder | 30 | // 构造TopHitOrder |
31 | - if (personalVectorFeatureSearch.getPersonalizedSearch(paramMap) != null) { | 31 | + if (personalVectorFeatureSearch.queryPersonalizedSearch(paramMap) != null) { |
32 | topHitOrder = "_score:desc"; | 32 | topHitOrder = "_score:desc"; |
33 | } | 33 | } |
34 | } | 34 | } |
@@ -36,7 +36,7 @@ public class RecommendShopAggregation extends AbstractAggregation { | @@ -36,7 +36,7 @@ public class RecommendShopAggregation extends AbstractAggregation { | ||
36 | this.simpleFieldAggs = new ArrayList<SimpleFieldAgg>(); | 36 | this.simpleFieldAggs = new ArrayList<SimpleFieldAgg>(); |
37 | simpleFieldAggs.add(new SimpleFieldAgg(aggName(), ProductIndexEsField.shopId, shopCount)); | 37 | simpleFieldAggs.add(new SimpleFieldAgg(aggName(), ProductIndexEsField.shopId, shopCount)); |
38 | // 构造topHit排序规则 | 38 | // 构造topHit排序规则 |
39 | - if (personalVectorFeatureSearch.getPersonalizedSearch(paramMap) != null) { | 39 | + if (personalVectorFeatureSearch.queryPersonalizedSearch(paramMap) != null) { |
40 | topHitOrder = "_score:desc"; | 40 | topHitOrder = "_score:desc"; |
41 | } | 41 | } |
42 | } | 42 | } |
@@ -6,7 +6,9 @@ import java.util.List; | @@ -6,7 +6,9 @@ import java.util.List; | ||
6 | import java.util.Map; | 6 | import java.util.Map; |
7 | import java.util.stream.Collectors; | 7 | import java.util.stream.Collectors; |
8 | 8 | ||
9 | +import com.yoho.search.base.utils.ConvertUtils; | ||
9 | import com.yoho.search.service.recall.config.SpecialShopConstants; | 10 | import com.yoho.search.service.recall.config.SpecialShopConstants; |
11 | +import org.apache.commons.collections.CollectionUtils; | ||
10 | import org.apache.commons.collections.MapUtils; | 12 | import org.apache.commons.collections.MapUtils; |
11 | import org.apache.commons.lang.StringUtils; | 13 | import org.apache.commons.lang.StringUtils; |
12 | import org.elasticsearch.common.lucene.search.function.CombineFunction; | 14 | import org.elasticsearch.common.lucene.search.function.CombineFunction; |
@@ -34,252 +36,257 @@ import com.yoho.search.service.scene.general.ProductCountService; | @@ -34,252 +36,257 @@ import com.yoho.search.service.scene.general.ProductCountService; | ||
34 | @Component | 36 | @Component |
35 | public class FunctionScoreSearchHelper { | 37 | public class FunctionScoreSearchHelper { |
36 | 38 | ||
37 | - private static final Logger logger = LoggerFactory.getLogger(FunctionScoreSearchHelper.class); | 39 | + private static final Logger logger = LoggerFactory.getLogger(FunctionScoreSearchHelper.class); |
38 | 40 | ||
39 | - @Autowired | ||
40 | - private SearchCommonHelper searchCommonHelper; | ||
41 | - @Autowired | ||
42 | - private PersonalVectorFeatureSearch personalVectorFeatureSearch; | ||
43 | - @Autowired | ||
44 | - private SearchDynamicConfigService dynamicConfig; | ||
45 | - @Autowired | ||
46 | - private SearchScorerFactory searchScorerFactory; | ||
47 | - @Autowired | ||
48 | - private ProductCountService productCountService; | 41 | + @Autowired |
42 | + private SearchCommonHelper searchCommonHelper; | ||
43 | + @Autowired | ||
44 | + private PersonalVectorFeatureSearch personalVectorFeatureSearch; | ||
45 | + @Autowired | ||
46 | + private SearchDynamicConfigService dynamicConfig; | ||
47 | + @Autowired | ||
48 | + private SearchScorerFactory searchScorerFactory; | ||
49 | + @Autowired | ||
50 | + private ProductCountService productCountService; | ||
49 | 51 | ||
50 | - // 普通个性化的时间维度 | ||
51 | - private static final FirstShelveTimeScore COMMON_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(30, 7, 23); | ||
52 | - // 新品到着的个性化时间维度 | ||
53 | - private static final FirstShelveTimeScore NEW_REC_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(4, 1, 3); | ||
54 | - // 模糊搜索的个性化时间维度 | ||
55 | - private static final FirstShelveTimeScore FUZZY_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(90, 60, 30); | 52 | + // 普通个性化的时间维度 |
53 | + private static final FirstShelveTimeScore COMMON_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(30, 7, 23); | ||
54 | + // 新品到着的个性化时间维度 | ||
55 | + private static final FirstShelveTimeScore NEW_REC_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(4, 1, 3); | ||
56 | + // 模糊搜索的个性化时间维度 | ||
57 | + private static final FirstShelveTimeScore FUZZY_FIRST_SHELVE_SCORE = new FirstShelveTimeScore(90, 60, 30); | ||
56 | 58 | ||
57 | - /** | ||
58 | - * 添加打分规则 | ||
59 | - * | ||
60 | - * @param queryBuilder | ||
61 | - * @param boolQueryBuilder | ||
62 | - * @param paramMap | ||
63 | - * @return | ||
64 | - */ | ||
65 | - public QueryBuilder buildFunctionScoreQueryBuild(QueryBuilder queryBuilder, BoolQueryBuilder boolQueryBuilder, Map<String, String> paramMap) { | ||
66 | - // 1、构造persionalFilter | ||
67 | - BoolQueryBuilder persionalFilter = this.genPersionalFilter(queryBuilder, boolQueryBuilder); | ||
68 | - // 2、获取打分器 | ||
69 | - String pageId = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_PAGEID, "0"); | ||
70 | - List<IScorer> scorers = this.getScorers(pageId, persionalFilter, paramMap); | ||
71 | - if (scorers == null || scorers.isEmpty()) { | ||
72 | - return new FunctionScoreQueryBuilder(queryBuilder); | ||
73 | - } | ||
74 | - // 3、构造functionScoreQueryBuilder | ||
75 | - YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders(); | ||
76 | - for (IScorer iScorer : scorers) { | ||
77 | - if(iScorer!=null){ | ||
78 | - iScorer.addScorer(yohoFilterFunctionBuilders); | ||
79 | - } | ||
80 | - } | ||
81 | - FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, yohoFilterFunctionBuilders.getFilterFunctionBuilders()); | ||
82 | - // 4、设置打分模式 | ||
83 | - functionScoreQueryBuilder.boostMode(CombineFunction.MULTIPLY); | ||
84 | - return functionScoreQueryBuilder; | ||
85 | - } | 59 | + /** |
60 | + * 添加打分规则 | ||
61 | + * | ||
62 | + * @param queryBuilder | ||
63 | + * @param boolQueryBuilder | ||
64 | + * @param paramMap | ||
65 | + * @return | ||
66 | + */ | ||
67 | + public QueryBuilder buildFunctionScoreQueryBuild(QueryBuilder queryBuilder, BoolQueryBuilder boolQueryBuilder, Map<String, String> paramMap) { | ||
68 | + // 1、构造persionalFilter | ||
69 | + BoolQueryBuilder persionalFilter = this.genPersionalFilter(queryBuilder, boolQueryBuilder); | ||
70 | + // 2、获取打分器 | ||
71 | + String pageId = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_PAGEID, "0"); | ||
72 | + List<IScorer> scorers = this.getScorers(pageId, persionalFilter, paramMap); | ||
73 | + if (scorers == null || scorers.isEmpty()) { | ||
74 | + return new FunctionScoreQueryBuilder(queryBuilder); | ||
75 | + } | ||
76 | + // 3、构造functionScoreQueryBuilder | ||
77 | + YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders(); | ||
78 | + for (IScorer iScorer : scorers) { | ||
79 | + if (iScorer != null) { | ||
80 | + iScorer.addScorer(yohoFilterFunctionBuilders); | ||
81 | + } | ||
82 | + } | ||
83 | + FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, yohoFilterFunctionBuilders.getFilterFunctionBuilders()); | ||
84 | + // 4、设置打分模式 | ||
85 | + functionScoreQueryBuilder.boostMode(CombineFunction.MULTIPLY); | ||
86 | + return functionScoreQueryBuilder; | ||
87 | + } | ||
86 | 88 | ||
87 | - private BoolQueryBuilder genPersionalFilter(QueryBuilder queryBuilder, BoolQueryBuilder boolQueryBuilder) { | ||
88 | - BoolQueryBuilder persionalFilter = QueryBuilders.boolQuery(); | ||
89 | - if (queryBuilder != null) { | ||
90 | - persionalFilter.must(queryBuilder); | ||
91 | - } | ||
92 | - if (boolQueryBuilder != null) { | ||
93 | - persionalFilter.must(boolQueryBuilder); | ||
94 | - } | ||
95 | - return persionalFilter; | ||
96 | - } | 89 | + private BoolQueryBuilder genPersionalFilter(QueryBuilder queryBuilder, BoolQueryBuilder boolQueryBuilder) { |
90 | + BoolQueryBuilder persionalFilter = QueryBuilders.boolQuery(); | ||
91 | + if (queryBuilder != null) { | ||
92 | + persionalFilter.must(queryBuilder); | ||
93 | + } | ||
94 | + if (boolQueryBuilder != null) { | ||
95 | + persionalFilter.must(boolQueryBuilder); | ||
96 | + } | ||
97 | + return persionalFilter; | ||
98 | + } | ||
97 | 99 | ||
98 | - private List<IScorer> getScorers(String pageId, BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
99 | - List<IScorer> scorers = null; | ||
100 | - switch (pageId) { | ||
101 | - case SearchPageIdDefine.PAGE_ID_SORT: | ||
102 | - scorers = this.getSortPageScorers(persionalFilter, paramMap); | ||
103 | - break; | ||
104 | - case SearchPageIdDefine.PAGE_ID_SEARCH: | ||
105 | - scorers = this.getFuzzyPageScorers(persionalFilter, paramMap); | ||
106 | - break; | ||
107 | - case SearchPageIdDefine.PAGE_ID_NEW: | ||
108 | - scorers = this.getNewArrivePageScorers(persionalFilter, paramMap); | ||
109 | - break; | ||
110 | - default: | ||
111 | - scorers = this.getOtherPageScorers(persionalFilter, paramMap); | ||
112 | - break; | ||
113 | - } | ||
114 | - return scorers; | ||
115 | - } | 100 | + private List<IScorer> getScorers(String pageId, BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { |
101 | + List<IScorer> scorers = null; | ||
102 | + switch (pageId) { | ||
103 | + case SearchPageIdDefine.PAGE_ID_SORT: | ||
104 | + scorers = this.getSortPageScorers(persionalFilter, paramMap); | ||
105 | + break; | ||
106 | + case SearchPageIdDefine.PAGE_ID_SEARCH: | ||
107 | + scorers = this.getFuzzyPageScorers(persionalFilter, paramMap); | ||
108 | + break; | ||
109 | + case SearchPageIdDefine.PAGE_ID_NEW: | ||
110 | + scorers = this.getNewArrivePageScorers(persionalFilter, paramMap); | ||
111 | + break; | ||
112 | + default: | ||
113 | + scorers = this.getOtherPageScorers(persionalFilter, paramMap); | ||
114 | + break; | ||
115 | + } | ||
116 | + return scorers; | ||
117 | + } | ||
116 | 118 | ||
117 | - // 品类页的打分器 | ||
118 | - private List<IScorer> getSortPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
119 | - List<IScorer> scorers = new ArrayList<IScorer>(); | ||
120 | - // 1、不是默认品类页,返回空列表 | ||
121 | - if (!searchCommonHelper.isSortPageDefault(paramMap)) { | ||
122 | - return scorers; | ||
123 | - } | ||
124 | - // 2、获取通用打分器 | ||
125 | - scorers.addAll(this.getCommonScorers(persionalFilter, paramMap)); | ||
126 | - // 3、添加首次上架时间的打分器 | ||
127 | - scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getOtherPageShelveTimeScore())); | ||
128 | - // 4、品类页添加加分SKN的打分器 | ||
129 | - scorers.add(searchScorerFactory.getAddScoreSknsScorer()); | ||
130 | - return scorers; | ||
131 | - } | ||
132 | - | 119 | + // 品类页的打分器 |
120 | + private List<IScorer> getSortPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
121 | + List<IScorer> scorers = new ArrayList<IScorer>(); | ||
122 | + // 1、不是默认品类页,返回空列表 | ||
123 | + if (!searchCommonHelper.isSortPageDefault(paramMap)) { | ||
124 | + return scorers; | ||
125 | + } | ||
126 | + // 2、获取通用打分器 | ||
127 | + scorers.addAll(this.getCommonScorers(persionalFilter, paramMap)); | ||
128 | + // 3、添加首次上架时间的打分器 | ||
129 | + scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getOtherPageShelveTimeScore())); | ||
130 | + // 4、品类页添加加分SKN的打分器 | ||
131 | + scorers.add(searchScorerFactory.getAddScoreSknsScorer()); | ||
132 | + return scorers; | ||
133 | + } | ||
133 | 134 | ||
134 | - // 模糊搜索页的打分器 | ||
135 | - private List<IScorer> getFuzzyPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
136 | - List<IScorer> scorers = new ArrayList<>(); | ||
137 | - // 1、不是默认搜索类页,返回空列表 | ||
138 | - if (!searchCommonHelper.isFuzzySearchPageDefault(paramMap)) { | ||
139 | - return scorers; | ||
140 | - } | ||
141 | - // 2、获取通用打分器 | ||
142 | - scorers.addAll(this.getCommonScorers(persionalFilter, paramMap)); | ||
143 | - // 3、添加首次上架时间的打分器 | ||
144 | - scorers.add(searchScorerFactory.getFirstShelveTimeScorer(FUZZY_FIRST_SHELVE_SCORE)); | ||
145 | - // 4、添加频道搜索 | ||
146 | - scorers.add(searchScorerFactory.getChannelSearchScorer(paramMap)); | ||
147 | - // 5、添加线下可售商品打分器 | ||
148 | - scorers.add(searchScorerFactory.getOfflineSaleOnlyScorer()); | ||
149 | - // 6、添加关键词完全匹配的打分器 | ||
150 | - String query = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_QUERY); | ||
151 | - if(StringUtils.isNotBlank(query)){ | ||
152 | - scorers.add(searchScorerFactory.getCsBrandKeyWordScorer(query)); | ||
153 | - } | ||
154 | - // 7、添加特殊店铺的打分器 | ||
155 | - scorers.add(searchScorerFactory.getSpecialShopScorer(SpecialShopConstants.DOWNGRADE_SHOPIDS, SpecialShopConstants.DOWNGRADE_SHOP_WEIGHT)); | ||
156 | - return scorers; | ||
157 | - } | ||
158 | 135 | ||
159 | - // 新品到着页的打分器 | ||
160 | - private List<IScorer> getNewArrivePageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
161 | - List<IScorer> scorers = new ArrayList<IScorer>(); | ||
162 | - if (searchCommonHelper.isNewRecPageDefault(paramMap)) { | ||
163 | - scorers.addAll(this.getCommonScorers(persionalFilter, paramMap)); | ||
164 | - scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getNewArrivalPageShelveTimeScore())); | ||
165 | - } else if (searchCommonHelper.isNewRecHeatValueDescSearch(paramMap)) { | ||
166 | - scorers.add(searchScorerFactory.getNewArriveHeatDescScorer());// 新品到着页的人气值排序 | ||
167 | - } | ||
168 | - return scorers; | ||
169 | - } | 136 | + // 模糊搜索页的打分器 |
137 | + private List<IScorer> getFuzzyPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
138 | + List<IScorer> scorers = new ArrayList<>(); | ||
139 | + // 1、不是默认搜索类页,返回空列表 | ||
140 | + if (!searchCommonHelper.isFuzzySearchPageDefault(paramMap)) { | ||
141 | + return scorers; | ||
142 | + } | ||
143 | + // 2、获取通用打分器 | ||
144 | + scorers.addAll(this.getCommonScorers(persionalFilter, paramMap)); | ||
145 | + // 3、添加首次上架时间的打分器 | ||
146 | + scorers.add(searchScorerFactory.getFirstShelveTimeScorer(FUZZY_FIRST_SHELVE_SCORE)); | ||
147 | + // 4、添加频道搜索 | ||
148 | + scorers.add(searchScorerFactory.getChannelSearchScorer(paramMap)); | ||
149 | + // 5、添加线下可售商品打分器 | ||
150 | + scorers.add(searchScorerFactory.getOfflineSaleOnlyScorer()); | ||
151 | + // 6、添加关键词完全匹配的打分器 | ||
152 | + String query = MapUtils.getString(paramMap, SearchRequestParams.PARAM_SEARCH_QUERY); | ||
153 | + if (StringUtils.isNotBlank(query)) { | ||
154 | + scorers.add(searchScorerFactory.getCsBrandKeyWordScorer(query)); | ||
155 | + } | ||
156 | + // 7、添加特殊店铺的打分器 | ||
157 | + scorers.add(searchScorerFactory.getSpecialShopScorer(SpecialShopConstants.DOWNGRADE_SHOPIDS, SpecialShopConstants.DOWNGRADE_SHOP_WEIGHT)); | ||
158 | + return scorers; | ||
159 | + } | ||
170 | 160 | ||
171 | - /** | ||
172 | - * 其他页面的打分规则 | ||
173 | - * | ||
174 | - * @param persionalFilter | ||
175 | - * @param paramMap | ||
176 | - */ | ||
177 | - private List<IScorer> getOtherPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
178 | - List<IScorer> scorers = new ArrayList<IScorer>(); | ||
179 | - if (!searchCommonHelper.isOrderEmpty(paramMap)) { | ||
180 | - return scorers; | ||
181 | - } | ||
182 | - scorers.addAll(this.getCommonScorers(persionalFilter, paramMap)); | ||
183 | - scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getOtherPageShelveTimeScore())); | ||
184 | - return scorers; | ||
185 | - } | 161 | + // 新品到着页的打分器 |
162 | + private List<IScorer> getNewArrivePageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
163 | + List<IScorer> scorers = new ArrayList<IScorer>(); | ||
164 | + if (searchCommonHelper.isNewRecPageDefault(paramMap)) { | ||
165 | + scorers.addAll(this.getCommonScorers(persionalFilter, paramMap)); | ||
166 | + scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getNewArrivalPageShelveTimeScore())); | ||
167 | + } else if (searchCommonHelper.isNewRecHeatValueDescSearch(paramMap)) { | ||
168 | + scorers.add(searchScorerFactory.getNewArriveHeatDescScorer());// 新品到着页的人气值排序 | ||
169 | + } | ||
170 | + return scorers; | ||
171 | + } | ||
186 | 172 | ||
187 | - // 公用的打分器 | ||
188 | - private List<IScorer> getCommonScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
189 | - // 1、传了order,则都不生效 | ||
190 | - if (!searchCommonHelper.isOrderEmpty(paramMap)) { | ||
191 | - return new ArrayList<IScorer>(); | ||
192 | - } | ||
193 | - List<IScorer> scorers = new ArrayList<IScorer>(); | ||
194 | - // 2、全球购商品 | ||
195 | - scorers.add(searchScorerFactory.getGlobalProductSearch(paramMap)); | ||
196 | - // 3、一高三低商品降分[非新品并且零交际的商品] | ||
197 | - scorers.add(searchScorerFactory.getProblemProductScorer()); | ||
198 | - // 4、first_product_skn | ||
199 | - scorers.add(searchScorerFactory.getFirstProductSknScorer(paramMap)); | ||
200 | - // 5、断码商品 | ||
201 | - //scorers.add(searchScorerFactory.getBreakSizeProductScorer(paramMap)); | ||
202 | - // 6、基于向量的个性化打分 | ||
203 | - scorers.add(this.getPersonalVectorFeatureScorer(persionalFilter, paramMap)); | ||
204 | - return scorers; | ||
205 | - } | 173 | + /** |
174 | + * 其他页面的打分规则 | ||
175 | + * | ||
176 | + * @param persionalFilter | ||
177 | + * @param paramMap | ||
178 | + */ | ||
179 | + private List<IScorer> getOtherPageScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
180 | + List<IScorer> scorers = new ArrayList<IScorer>(); | ||
181 | + if (!searchCommonHelper.isOrderEmpty(paramMap)) { | ||
182 | + return scorers; | ||
183 | + } | ||
184 | + scorers.addAll(this.getCommonScorers(persionalFilter, paramMap)); | ||
185 | + scorers.add(searchScorerFactory.getFirstShelveTimeScorer(getOtherPageShelveTimeScore())); | ||
186 | + return scorers; | ||
187 | + } | ||
206 | 188 | ||
207 | - /** | ||
208 | - * 个性化的打分器 | ||
209 | - * | ||
210 | - * @param persionalFilter | ||
211 | - * @param paramMap | ||
212 | - * @return | ||
213 | - */ | ||
214 | - private IScorer getPersonalVectorFeatureScorer(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
215 | - // 1、判断是否开启了个性化搜索 | ||
216 | - if (!searchCommonHelper.isNeedPersonalSearch(paramMap)) { | ||
217 | - return null; | ||
218 | - } | ||
219 | - // 2、获取PersonalizedSearch | ||
220 | - PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap); | ||
221 | - if (personalizedSearch == null) { | ||
222 | - return null; | ||
223 | - } | ||
224 | - // 3、为个性化打分添加filter条件 | ||
225 | - BoolQueryBuilder scoreFilter = productCountService.genScoreFilter(persionalFilter); | ||
226 | - return searchScorerFactory.getFeatureFactorScorer(scoreFilter, personalizedSearch.getUserVectorFeature(), personalizedSearch.getVectorFeatureVersion()); | ||
227 | - } | 189 | + // 公用的打分器 |
190 | + private List<IScorer> getCommonScorers(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
191 | + // 1、传了order,则都不生效 | ||
192 | + if (!searchCommonHelper.isOrderEmpty(paramMap)) { | ||
193 | + return new ArrayList<IScorer>(); | ||
194 | + } | ||
195 | + List<IScorer> scorers = new ArrayList<IScorer>(); | ||
196 | + // 2、全球购商品 | ||
197 | + scorers.add(searchScorerFactory.getGlobalProductSearch(paramMap)); | ||
198 | + // 3、一高三低商品降分[非新品并且零交际的商品] | ||
199 | + scorers.add(searchScorerFactory.getProblemProductScorer()); | ||
200 | + // 4、first_product_skn | ||
201 | + scorers.add(searchScorerFactory.getFirstProductSknScorer(paramMap)); | ||
202 | + // 5、断码商品 | ||
203 | + //scorers.add(searchScorerFactory.getBreakSizeProductScorer(paramMap)); | ||
204 | + // 6、基于向量的个性化打分 | ||
205 | + scorers.add(this.getPersonalVectorFeatureScorer(persionalFilter, paramMap)); | ||
206 | + return scorers; | ||
207 | + } | ||
228 | 208 | ||
229 | - /** | ||
230 | - * 直接使用商品特征的向量用来做个性化打分 | ||
231 | - * | ||
232 | - * @param queryBuilder | ||
233 | - * @param productVectorFeature | ||
234 | - * @return | ||
235 | - */ | ||
236 | - public QueryBuilder buildFunctionScoreQueryBuildWithProductFeature(QueryBuilder queryBuilder, String productVectorFeature) { | ||
237 | - // 1. 获取商品特征向量 | ||
238 | - if (StringUtils.isBlank(productVectorFeature)) { | ||
239 | - return queryBuilder; | ||
240 | - } | ||
241 | - // 2. 传入参数调用脚本,以商品特征代替用户特征 | ||
242 | - String[] productVectorFeatures = productVectorFeature.split("\\|", 2); | ||
243 | - if (productVectorFeatures.length != 2) { | ||
244 | - return queryBuilder; | ||
245 | - } | ||
246 | - IScorer scorer = searchScorerFactory.getFeatureFactorScorer(queryBuilder, productVectorFeatures[1], productVectorFeatures[0]); | ||
247 | - YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders(); | ||
248 | - if(scorer!=null){ | ||
249 | - scorer.addScorer(yohoFilterFunctionBuilders); | ||
250 | - } | ||
251 | - FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder,yohoFilterFunctionBuilders.getFilterFunctionBuilders()); | ||
252 | - return functionScoreQueryBuilder; | ||
253 | - } | 209 | + /** |
210 | + * 个性化的打分器 | ||
211 | + * | ||
212 | + * @param persionalFilter | ||
213 | + * @param paramMap | ||
214 | + * @return | ||
215 | + */ | ||
216 | + private IScorer getPersonalVectorFeatureScorer(BoolQueryBuilder persionalFilter, Map<String, String> paramMap) { | ||
217 | + // 1、判断是否开启了个性化搜索 | ||
218 | + if (!searchCommonHelper.isNeedPersonalSearch(paramMap)) { | ||
219 | + return null; | ||
220 | + } | ||
221 | + // 2、获取PersonalizedSearch | ||
222 | + PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.queryPersonalizedSearch(paramMap); | ||
223 | + if (personalizedSearch == null) { | ||
224 | + return null; | ||
225 | + } | ||
226 | + // 3、为个性化打分添加filter条件 | ||
227 | + BoolQueryBuilder scoreFilter = productCountService.genScoreFilter(persionalFilter); | ||
228 | + return searchScorerFactory.getFeatureFactorScorer(scoreFilter, personalizedSearch.getVectorVersion(), personalizedSearch.getVectorFeatures()); | ||
229 | + } | ||
254 | 230 | ||
255 | - // 新品到着页的根据首次上架时间衰减函数规则值 | ||
256 | - private FirstShelveTimeScore getNewArrivalPageShelveTimeScore() { | ||
257 | - try { | ||
258 | - String values = dynamicConfig.getNewArrivalPageDecayRuleValue(); | ||
259 | - List<Integer> valueList = Arrays.asList(values.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList()); | ||
260 | - Assert.isTrue(valueList.size() == 2, "For " + values); | ||
261 | - Integer scale = valueList.get(0) - valueList.get(1); | ||
262 | - Assert.isTrue(scale.intValue() > 0, "For " + values); | ||
263 | - return new FirstShelveTimeScore(valueList.get(0), valueList.get(1), scale); | ||
264 | - } catch (Exception e) { | ||
265 | - logger.warn(e.getMessage(), e); | ||
266 | - return NEW_REC_FIRST_SHELVE_SCORE; | ||
267 | - } | ||
268 | - } | 231 | + /** |
232 | + * 直接使用商品特征的向量用来做个性化打分 | ||
233 | + * | ||
234 | + * @param queryBuilder | ||
235 | + * @param productVectorFeature | ||
236 | + * @return | ||
237 | + */ | ||
238 | + public QueryBuilder buildFunctionScoreQueryBuildWithProductFeature(QueryBuilder queryBuilder, String productVectorFeature) { | ||
239 | + // 1. 获取商品特征向量 | ||
240 | + if (StringUtils.isBlank(productVectorFeature)) { | ||
241 | + return queryBuilder; | ||
242 | + } | ||
243 | + // 2. 传入参数调用脚本,以商品特征代替用户特征 | ||
244 | + String[] productVectorFeatures = productVectorFeature.split("\\|", 2); | ||
245 | + if (productVectorFeatures.length != 2) { | ||
246 | + return queryBuilder; | ||
247 | + } | ||
248 | + // 3、参数检测 | ||
249 | + String featureVersion = productVectorFeatures[0]; | ||
250 | + List<Double> featureFactors = ConvertUtils.stringToDoubleList(productVectorFeatures[1], ","); | ||
251 | + if (StringUtils.isBlank(featureVersion) || CollectionUtils.isEmpty(featureFactors)) { | ||
252 | + return queryBuilder; | ||
253 | + } | ||
254 | + //4、构造scorer | ||
255 | + IScorer scorer = searchScorerFactory.getFeatureFactorScorer(queryBuilder, featureVersion, featureFactors); | ||
256 | + YohoFilterFunctionBuilders yohoFilterFunctionBuilders = new YohoFilterFunctionBuilders(); | ||
257 | + scorer.addScorer(yohoFilterFunctionBuilders); | ||
258 | + FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(queryBuilder, yohoFilterFunctionBuilders.getFilterFunctionBuilders()); | ||
259 | + return functionScoreQueryBuilder; | ||
260 | + } | ||
269 | 261 | ||
270 | - // 非新品到着页的根据首次上架时间衰减函数规则值 | ||
271 | - private FirstShelveTimeScore getOtherPageShelveTimeScore() { | ||
272 | - try { | ||
273 | - String values = dynamicConfig.getOtherPageDecayRuleValue(); | ||
274 | - List<Integer> valueList = Arrays.asList(values.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList()); | ||
275 | - Assert.isTrue(valueList.size() == 2, "For " + values); | ||
276 | - Integer scale = valueList.get(0) - valueList.get(1); | ||
277 | - Assert.isTrue(scale.intValue() > 0, "For " + values); | ||
278 | - return new FirstShelveTimeScore(valueList.get(0), valueList.get(1), scale); | ||
279 | - } catch (Exception e) { | ||
280 | - logger.warn(e.getMessage(), e); | ||
281 | - return COMMON_FIRST_SHELVE_SCORE; | ||
282 | - } | ||
283 | - } | 262 | + // 新品到着页的根据首次上架时间衰减函数规则值 |
263 | + private FirstShelveTimeScore getNewArrivalPageShelveTimeScore() { | ||
264 | + try { | ||
265 | + String values = dynamicConfig.getNewArrivalPageDecayRuleValue(); | ||
266 | + List<Integer> valueList = Arrays.asList(values.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList()); | ||
267 | + Assert.isTrue(valueList.size() == 2, "For " + values); | ||
268 | + Integer scale = valueList.get(0) - valueList.get(1); | ||
269 | + Assert.isTrue(scale.intValue() > 0, "For " + values); | ||
270 | + return new FirstShelveTimeScore(valueList.get(0), valueList.get(1), scale); | ||
271 | + } catch (Exception e) { | ||
272 | + logger.warn(e.getMessage(), e); | ||
273 | + return NEW_REC_FIRST_SHELVE_SCORE; | ||
274 | + } | ||
275 | + } | ||
276 | + | ||
277 | + // 非新品到着页的根据首次上架时间衰减函数规则值 | ||
278 | + private FirstShelveTimeScore getOtherPageShelveTimeScore() { | ||
279 | + try { | ||
280 | + String values = dynamicConfig.getOtherPageDecayRuleValue(); | ||
281 | + List<Integer> valueList = Arrays.asList(values.split(",")).stream().map(Integer::valueOf).collect(Collectors.toList()); | ||
282 | + Assert.isTrue(valueList.size() == 2, "For " + values); | ||
283 | + Integer scale = valueList.get(0) - valueList.get(1); | ||
284 | + Assert.isTrue(scale.intValue() > 0, "For " + values); | ||
285 | + return new FirstShelveTimeScore(valueList.get(0), valueList.get(1), scale); | ||
286 | + } catch (Exception e) { | ||
287 | + logger.warn(e.getMessage(), e); | ||
288 | + return COMMON_FIRST_SHELVE_SCORE; | ||
289 | + } | ||
290 | + } | ||
284 | 291 | ||
285 | } | 292 | } |
@@ -182,7 +182,7 @@ public class UserRecallResponseBuilder { | @@ -182,7 +182,7 @@ public class UserRecallResponseBuilder { | ||
182 | //1、获取用户向量 | 182 | //1、获取用户向量 |
183 | Map<String, String> paramMap = new HashMap<>(); | 183 | Map<String, String> paramMap = new HashMap<>(); |
184 | paramMap.put("uid", "" + uid); | 184 | paramMap.put("uid", "" + uid); |
185 | - PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.getPersonalizedSearch(paramMap); | 185 | + PersonalizedSearch personalizedSearch = personalVectorFeatureSearch.queryPersonalizedSearch(paramMap); |
186 | UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch); | 186 | UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch); |
187 | //2、计算相关性 | 187 | //2、计算相关性 |
188 | int recommendSknIndex = 10000; | 188 | int recommendSknIndex = 10000; |
1 | package com.yoho.search.service.recall.beans.persional; | 1 | package com.yoho.search.service.recall.beans.persional; |
2 | 2 | ||
3 | import com.yoho.search.base.helper.Word2VectorCalculator; | 3 | import com.yoho.search.base.helper.Word2VectorCalculator; |
4 | +import com.yoho.search.base.utils.ConvertUtils; | ||
4 | import com.yoho.search.core.personalized.models.PersonalizedSearch; | 5 | import com.yoho.search.core.personalized.models.PersonalizedSearch; |
5 | import com.yoho.search.service.recall.models.personal.UserFeatureFactor; | 6 | import com.yoho.search.service.recall.models.personal.UserFeatureFactor; |
7 | +import org.apache.commons.collections.CollectionUtils; | ||
6 | import org.apache.commons.lang.StringUtils; | 8 | import org.apache.commons.lang.StringUtils; |
7 | import org.slf4j.Logger; | 9 | import org.slf4j.Logger; |
8 | import org.slf4j.LoggerFactory; | 10 | import org.slf4j.LoggerFactory; |
9 | import org.springframework.stereotype.Component; | 11 | import org.springframework.stereotype.Component; |
10 | 12 | ||
11 | -import java.util.ArrayList; | ||
12 | import java.util.List; | 13 | import java.util.List; |
13 | 14 | ||
14 | @Component | 15 | @Component |
@@ -21,23 +22,28 @@ public class ProductFeatureFactorComponent { | @@ -21,23 +22,28 @@ public class ProductFeatureFactorComponent { | ||
21 | 22 | ||
22 | public double calProductFeatureFactor(UserFeatureFactor userFeatureFactor, String productFeatureFactor) { | 23 | public double calProductFeatureFactor(UserFeatureFactor userFeatureFactor, String productFeatureFactor) { |
23 | try { | 24 | try { |
25 | + //商品向量不存在,则返回 | ||
26 | + if (StringUtils.isBlank(productFeatureFactor)) { | ||
27 | + return 0; | ||
28 | + } | ||
24 | //用户向量不存在,则返回0 | 29 | //用户向量不存在,则返回0 |
25 | - if (userFeatureFactor == null || StringUtils.isBlank(userFeatureFactor.getVectorFeatureVersion())) { | 30 | + if (userFeatureFactor == null || StringUtils.isBlank(userFeatureFactor.getVectorVersion())) { |
26 | return 0; | 31 | return 0; |
27 | } | 32 | } |
28 | - if (StringUtils.isBlank(productFeatureFactor)) { | 33 | + if (CollectionUtils.isEmpty(userFeatureFactor.getVectorFeatureList())) { |
29 | return 0; | 34 | return 0; |
30 | } | 35 | } |
31 | - String versionPrefix = userFeatureFactor.getVectorFeatureVersion() + "|"; | 36 | + //版本不匹配,则返回0 |
37 | + String versionPrefix = userFeatureFactor.getVectorVersion() + "|"; | ||
32 | if (!productFeatureFactor.trim().startsWith(versionPrefix)) { | 38 | if (!productFeatureFactor.trim().startsWith(versionPrefix)) { |
33 | return 0; | 39 | return 0; |
34 | } | 40 | } |
35 | - String[] productFeatureFactorArr = productFeatureFactor.trim().substring(versionPrefix.length()).split(","); | ||
36 | - List<Double> productFeatureVectors = this.arrayToList(productFeatureFactorArr); | ||
37 | - if (productFeatureVectors == null || productFeatureVectors.size() != userFeatureFactor.getUserFeatureVectorList().size()) { | 41 | + //执行计算 |
42 | + List<Double> productFeatureVectors = ConvertUtils.stringToDoubleList(productFeatureFactor.trim().substring(versionPrefix.length()), ","); | ||
43 | + if (productFeatureVectors == null || productFeatureVectors.size() != userFeatureFactor.getVectorFeatureList().size()) { | ||
38 | return 0; | 44 | return 0; |
39 | } | 45 | } |
40 | - double score = Word2VectorCalculator.calScore(userFeatureFactor.getUserFeatureVectorList(), userFeatureFactor.getUserFeatureVectorNorm(), productFeatureVectors); | 46 | + double score = Word2VectorCalculator.calScore(userFeatureFactor.getVectorFeatureList(), userFeatureFactor.getUserFeatureVectorNorm(), productFeatureVectors); |
41 | double finalScore = baseConstant + factorConstant * score; | 47 | double finalScore = baseConstant + factorConstant * score; |
42 | return finalScore; | 48 | return finalScore; |
43 | } catch (Exception e) { | 49 | } catch (Exception e) { |
@@ -46,22 +52,12 @@ public class ProductFeatureFactorComponent { | @@ -46,22 +52,12 @@ public class ProductFeatureFactorComponent { | ||
46 | } | 52 | } |
47 | } | 53 | } |
48 | 54 | ||
49 | - private List<Double> arrayToList(String[] productFeatureFactorStrArr) { | ||
50 | - List<Double> results = new ArrayList<>(); | ||
51 | - if (productFeatureFactorStrArr == null) { | ||
52 | - return results; | ||
53 | - } | ||
54 | - for (String productFeatureFactor : productFeatureFactorStrArr) { | ||
55 | - results.add(Double.parseDouble(productFeatureFactor)); | ||
56 | - } | ||
57 | - return results; | ||
58 | - } | ||
59 | - | ||
60 | public static void main(String[] args) { | 55 | public static void main(String[] args) { |
61 | - PersonalizedSearch personalizedSearch = new PersonalizedSearch("1", "20180408", "0.342045,-0.547933,0.291732,-0.056515,-0.182701,0.31113,0.151578,0.087678,-0.045536,-0.525699,-0.394715,-0.103153,-0.05575,-0.540641,0.028046,-0.193109,-0.003591,0.180923,0.290261,0.532309,-0.202463,-0.047271,-0.246197,0.324561,0.188814,0.36475,0.079007,0.455753,-0.11848,-0.135874,-0.187155,-0.055342,-0.12525,0.210669,-0.388331,-0.197123,0.132309,-0.4231,0.217752,-0.203266,0.190836,0.373428,-0.0102,-0.038654,0.2379,0.044424,0.071826,-0.201054,0.257434,0.141901,-0.390064,0.437099,0.559701,-0.040162,-0.193089,0.442338,-0.141678,-0.049696,0.315545,-0.028972,0.278694,-0.064345,-0.327943,0.103025,-0.40344,-0.34269,-0.237931,0.287046,0.139693,-0.38454,0.019959,-0.156907,0.374996,-0.074558,-0.019391,0.050522,0.315171,0.211605,-0.15418,0.502362,0.10184,0.153274,0.592659,-0.010284,0.28029,0.319741,-0.164559,0.286884,0.420483,-0.628866,-0.172259,0.027954,-0.411674,0.376585,0.322832,0.352039,0.078705,0.045152,0.139083,-0.164182"); | 56 | + List<Double> array = ConvertUtils.stringToDoubleList("0.342045,-0.547933,0.291732,-0.056515,-0.182701,0.31113,0.151578,0.087678,-0.045536,-0.525699,-0.394715,-0.103153,-0.05575,-0.540641,0.028046,-0.193109,-0.003591,0.180923,0.290261,0.532309,-0.202463,-0.047271,-0.246197,0.324561,0.188814,0.36475,0.079007,0.455753,-0.11848,-0.135874,-0.187155,-0.055342,-0.12525,0.210669,-0.388331,-0.197123,0.132309,-0.4231,0.217752,-0.203266,0.190836,0.373428,-0.0102,-0.038654,0.2379,0.044424,0.071826,-0.201054,0.257434,0.141901,-0.390064,0.437099,0.559701,-0.040162,-0.193089,0.442338,-0.141678,-0.049696,0.315545,-0.028972,0.278694,-0.064345,-0.327943,0.103025,-0.40344,-0.34269,-0.237931,0.287046,0.139693,-0.38454,0.019959,-0.156907,0.374996,-0.074558,-0.019391,0.050522,0.315171,0.211605,-0.15418,0.502362,0.10184,0.153274,0.592659,-0.010284,0.28029,0.319741,-0.164559,0.286884,0.420483,-0.628866,-0.172259,0.027954,-0.411674,0.376585,0.322832,0.352039,0.078705,0.045152,0.139083,-0.164182", ","); |
57 | + PersonalizedSearch personalizedSearch = new PersonalizedSearch("1", "20180408", array); | ||
62 | UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch); | 58 | UserFeatureFactor userFeatureFactor = new UserFeatureFactor(personalizedSearch); |
63 | - String productFeatureFactor = "20180408|0.342045,-0.547933,0.291732,-0.056515,-0.182701,0.31113,0.151578,0.087678,-0.045536,-0.525699,-0.394715,-0.103153,-0.05575,-0.540641,0.028046,-0.193109,-0.003591,0.180923,0.290261,0.532309,-0.202463,-0.047271,-0.246197,0.324561,0.188814,0.36475,0.079007,0.455753,-0.11848,-0.135874,-0.187155,-0.055342,-0.12525,0.210669,-0.388331,-0.197123,0.132309,-0.4231,0.217752,-0.203266,0.190836,0.373428,-0.0102,-0.038654,0.2379,0.044424,0.071826,-0.201054,0.257434,0.141901,-0.390064,0.437099,0.559701,-0.040162,-0.193089,0.442338,-0.141678,-0.049696,0.315545,-0.028972,0.278694,-0.064345,-0.327943,0.103025,-0.40344,-0.34269,-0.237931,0.287046,0.139693,-0.38454,0.019959,-0.156907,0.374996,-0.074558,-0.019391,0.050522,0.315171,0.211605,-0.15418,0.502362,0.10184,0.153274,0.592659,-0.010284,0.28029,0.319741,-0.164559,0.286884,0.420483,-0.628866,-0.172259,0.027954,-0.411674,0.376585,0.322832,0.352039,0.078705,0.045152,0.139083,-0.164182"; | ||
64 | - System.out.println(new ProductFeatureFactorComponent().calProductFeatureFactor(userFeatureFactor,productFeatureFactor)); | 59 | + String productFeatureFactor = "20180408|1.342045,-0.547933,0.291732,-0.056515,-0.182701,0.31113,0.151578,0.087678,-0.045536,-0.525699,-0.394715,-0.103153,-0.05575,-0.540641,0.028046,-0.193109,-0.003591,0.180923,0.290261,0.532309,-0.202463,-0.047271,-0.246197,0.324561,0.188814,0.36475,0.079007,0.455753,-0.11848,-0.135874,-0.187155,-0.055342,-0.12525,0.210669,-0.388331,-0.197123,0.132309,-0.4231,0.217752,-0.203266,0.190836,0.373428,-0.0102,-0.038654,0.2379,0.044424,0.071826,-0.201054,0.257434,0.141901,-0.390064,0.437099,0.559701,-0.040162,-0.193089,0.442338,-0.141678,-0.049696,0.315545,-0.028972,0.278694,-0.064345,-0.327943,0.103025,-0.40344,-0.34269,-0.237931,0.287046,0.139693,-0.38454,0.019959,-0.156907,0.374996,-0.074558,-0.019391,0.050522,0.315171,0.211605,-0.15418,0.502362,0.10184,0.153274,0.592659,-0.010284,0.28029,0.319741,-0.164559,0.286884,0.420483,-0.628866,-0.172259,0.027954,-0.411674,0.376585,0.322832,0.352039,0.078705,0.045152,0.139083,-0.164182"; |
60 | + System.out.println(new ProductFeatureFactorComponent().calProductFeatureFactor(userFeatureFactor, productFeatureFactor)); | ||
65 | } | 61 | } |
66 | 62 | ||
67 | } | 63 | } |
1 | package com.yoho.search.service.recall.models.personal; | 1 | package com.yoho.search.service.recall.models.personal; |
2 | 2 | ||
3 | import com.yoho.search.core.personalized.models.PersonalizedSearch; | 3 | import com.yoho.search.core.personalized.models.PersonalizedSearch; |
4 | -import org.apache.commons.lang.StringUtils; | 4 | +import org.apache.commons.collections.CollectionUtils; |
5 | import org.slf4j.Logger; | 5 | import org.slf4j.Logger; |
6 | import org.slf4j.LoggerFactory; | 6 | import org.slf4j.LoggerFactory; |
7 | 7 | ||
8 | -import java.util.ArrayList; | ||
9 | import java.util.List; | 8 | import java.util.List; |
10 | 9 | ||
11 | public class UserFeatureFactor { | 10 | public class UserFeatureFactor { |
12 | 11 | ||
13 | - private static final Logger logger = LoggerFactory.getLogger(UserFeatureFactor.class); | ||
14 | - | ||
15 | - private List<Double> userFeatureVectorList = null; | ||
16 | - private double userFeatureVectorNorm = 0.0D; | ||
17 | - private String vectorFeatureVersion; | ||
18 | - | ||
19 | - public UserFeatureFactor(PersonalizedSearch personalizedSearch) { | ||
20 | - try { | ||
21 | - if (personalizedSearch == null) { | ||
22 | - return; | ||
23 | - } | ||
24 | - this.vectorFeatureVersion = personalizedSearch.getVectorFeatureVersion(); | ||
25 | - String userVectorFeature = personalizedSearch.getUserVectorFeature(); | ||
26 | - if(StringUtils.isBlank(userVectorFeature)){ | ||
27 | - return; | ||
28 | - } | ||
29 | - String[] userFeatureFactorStrArr = userVectorFeature.split(","); | ||
30 | - if(userFeatureFactorStrArr.length==0){ | ||
31 | - return; | ||
32 | - } | ||
33 | - userFeatureVectorList = new ArrayList<>(userFeatureFactorStrArr.length); | ||
34 | - for (String userFeatureFactorStr : userFeatureFactorStrArr) { | ||
35 | - double userFeatureVector = Double.parseDouble(userFeatureFactorStr.trim()); | ||
36 | - userFeatureVectorList.add(userFeatureVector); | ||
37 | - userFeatureVectorNorm += userFeatureVector * userFeatureVector; | ||
38 | - } | ||
39 | - }catch (Exception e){ | ||
40 | - logger.error(e.getMessage()); | ||
41 | - } | ||
42 | - } | ||
43 | - | ||
44 | - public List<Double> getUserFeatureVectorList() { | ||
45 | - return userFeatureVectorList; | ||
46 | - } | ||
47 | - | ||
48 | - public double getUserFeatureVectorNorm() { | ||
49 | - return userFeatureVectorNorm; | ||
50 | - } | ||
51 | - | ||
52 | - public String getVectorFeatureVersion() { | ||
53 | - return vectorFeatureVersion; | ||
54 | - } | 12 | + private static final Logger logger = LoggerFactory.getLogger(UserFeatureFactor.class); |
13 | + | ||
14 | + private String vectorVersion; | ||
15 | + private List<Double> vectorFeatureList = null; | ||
16 | + private double userFeatureVectorNorm = 0.0D; | ||
17 | + | ||
18 | + public UserFeatureFactor(PersonalizedSearch personalizedSearch) { | ||
19 | + try { | ||
20 | + if (personalizedSearch == null) { | ||
21 | + return; | ||
22 | + } | ||
23 | + this.vectorVersion = personalizedSearch.getVectorVersion(); | ||
24 | + this.vectorFeatureList = personalizedSearch.getVectorFeatures(); | ||
25 | + if (CollectionUtils.isEmpty(vectorFeatureList)) { | ||
26 | + return; | ||
27 | + } | ||
28 | + for (Double vectorFeature : vectorFeatureList) { | ||
29 | + userFeatureVectorNorm += vectorFeature * vectorFeature; | ||
30 | + } | ||
31 | + } catch (Exception e) { | ||
32 | + logger.error(e.getMessage()); | ||
33 | + } | ||
34 | + } | ||
35 | + | ||
36 | + public String getVectorVersion() { | ||
37 | + return vectorVersion; | ||
38 | + } | ||
39 | + | ||
40 | + public List<Double> getVectorFeatureList() { | ||
41 | + return vectorFeatureList; | ||
42 | + } | ||
43 | + | ||
44 | + public double getUserFeatureVectorNorm() { | ||
45 | + return userFeatureVectorNorm; | ||
46 | + } | ||
47 | + | ||
55 | } | 48 | } |
@@ -102,8 +102,8 @@ public class SearchScorerFactory { | @@ -102,8 +102,8 @@ public class SearchScorerFactory { | ||
102 | } | 102 | } |
103 | 103 | ||
104 | // 获取【向量余弦夹角】的打分器 | 104 | // 获取【向量余弦夹角】的打分器 |
105 | - public IScorer getFeatureFactorScorer(QueryBuilder scoreFilter, String featureFactors, String featureVersion) { | ||
106 | - return new FeatureFactorScorer(scoreFilter, featureFactors, featureVersion); | 105 | + public IScorer getFeatureFactorScorer(QueryBuilder scoreFilter,String featureVersion, List<Double> featureFactors) { |
106 | + return new FeatureFactorScorer(scoreFilter,featureVersion,featureFactors); | ||
107 | } | 107 | } |
108 | 108 | ||
109 | public IScorer getOfflineSaleOnlyScorer() { | 109 | public IScorer getOfflineSaleOnlyScorer() { |
1 | package com.yoho.search.service.scorer.impl; | 1 | package com.yoho.search.service.scorer.impl; |
2 | 2 | ||
3 | import java.util.HashMap; | 3 | import java.util.HashMap; |
4 | +import java.util.List; | ||
4 | import java.util.Map; | 5 | import java.util.Map; |
5 | 6 | ||
7 | +import org.apache.commons.collections.CollectionUtils; | ||
8 | +import org.apache.commons.lang.StringUtils; | ||
6 | import org.elasticsearch.index.query.QueryBuilder; | 9 | import org.elasticsearch.index.query.QueryBuilder; |
7 | import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; | 10 | import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; |
8 | import org.elasticsearch.script.Script; | 11 | import org.elasticsearch.script.Script; |
@@ -21,22 +24,22 @@ public class FeatureFactorScorer implements IScorer { | @@ -21,22 +24,22 @@ public class FeatureFactorScorer implements IScorer { | ||
21 | private static final Double FACTOR_CONSTANT = 0.4D; | 24 | private static final Double FACTOR_CONSTANT = 0.4D; |
22 | 25 | ||
23 | private QueryBuilder scoreFilter; | 26 | private QueryBuilder scoreFilter; |
24 | - private String featureFactors; | ||
25 | private String featureVersion; | 27 | private String featureVersion; |
28 | + private String featureFactorString; | ||
26 | 29 | ||
27 | - public FeatureFactorScorer(QueryBuilder scoreFilter, String featureFactors, String featureVersion) { | 30 | + public FeatureFactorScorer(QueryBuilder scoreFilter, String featureVersion,List<Double> featureFactors) { |
28 | super(); | 31 | super(); |
29 | this.scoreFilter = scoreFilter; | 32 | this.scoreFilter = scoreFilter; |
30 | - this.featureFactors = featureFactors; | ||
31 | this.featureVersion = featureVersion; | 33 | this.featureVersion = featureVersion; |
34 | + this.featureFactorString = StringUtils.join(featureFactors,","); | ||
32 | } | 35 | } |
33 | 36 | ||
34 | @Override | 37 | @Override |
35 | public void addScorer(YohoFilterFunctionBuilders yohoFilterFunctionBuilders) { | 38 | public void addScorer(YohoFilterFunctionBuilders yohoFilterFunctionBuilders) { |
36 | Map<String, Object> scriptParams = new HashMap<>(); | 39 | Map<String, Object> scriptParams = new HashMap<>(); |
37 | scriptParams.put("field", "productFeatureFactor"); | 40 | scriptParams.put("field", "productFeatureFactor"); |
38 | - scriptParams.put("userFeatureFactors", featureFactors); | ||
39 | scriptParams.put("vectorFeatureVersion", featureVersion); | 41 | scriptParams.put("vectorFeatureVersion", featureVersion); |
42 | + scriptParams.put("userFeatureFactors", featureFactorString); | ||
40 | scriptParams.put("baseConstant", BASE_CONSTANT); | 43 | scriptParams.put("baseConstant", BASE_CONSTANT); |
41 | scriptParams.put("factorConstant", FACTOR_CONSTANT); | 44 | scriptParams.put("factorConstant", FACTOR_CONSTANT); |
42 | Script script = new Script(ScriptType.INLINE, "native", "feature_factor_vector_score", scriptParams); | 45 | Script script = new Script(ScriptType.INLINE, "native", "feature_factor_vector_score", scriptParams); |
1 | package com.yoho.search.service.scorer.personal; | 1 | package com.yoho.search.service.scorer.personal; |
2 | 2 | ||
3 | import com.yoho.search.aop.cache.SearchCacheAble; | 3 | import com.yoho.search.aop.cache.SearchCacheAble; |
4 | +import com.yoho.search.base.utils.ConvertUtils; | ||
4 | import com.yoho.search.cache.CacheType; | 5 | import com.yoho.search.cache.CacheType; |
5 | import com.yoho.search.core.personalized.models.PersonalizedSearch; | 6 | import com.yoho.search.core.personalized.models.PersonalizedSearch; |
6 | import com.yoho.search.core.personalized.service.BidataServiceCaller; | 7 | import com.yoho.search.core.personalized.service.BidataServiceCaller; |
7 | import com.yoho.search.core.personalized.service.PersonalVersionManager; | 8 | import com.yoho.search.core.personalized.service.PersonalVersionManager; |
9 | +import org.apache.commons.collections.CollectionUtils; | ||
8 | import org.apache.commons.lang3.StringUtils; | 10 | import org.apache.commons.lang3.StringUtils; |
9 | import org.slf4j.Logger; | 11 | import org.slf4j.Logger; |
10 | import org.slf4j.LoggerFactory; | 12 | import org.slf4j.LoggerFactory; |
11 | import org.springframework.beans.factory.annotation.Autowired; | 13 | import org.springframework.beans.factory.annotation.Autowired; |
12 | import org.springframework.stereotype.Service; | 14 | import org.springframework.stereotype.Service; |
13 | 15 | ||
16 | +import java.util.List; | ||
14 | import java.util.Map; | 17 | import java.util.Map; |
15 | 18 | ||
16 | @Service | 19 | @Service |
@@ -23,8 +26,8 @@ public class PersonalVectorFeatureSearch { | @@ -23,8 +26,8 @@ public class PersonalVectorFeatureSearch { | ||
23 | @Autowired | 26 | @Autowired |
24 | private BidataServiceCaller bidataServiceCaller; | 27 | private BidataServiceCaller bidataServiceCaller; |
25 | 28 | ||
26 | - @SearchCacheAble(cacheInMinute = 30, cacheName = "PERSIONAL_VECTOR", returnClass = PersonalizedSearch.class, cacheType = CacheType.SEARCH_REDIS, includeParams = { "uid" }) | ||
27 | - public PersonalizedSearch getPersonalizedSearch(Map<String, String> paramMap) { | 29 | + @SearchCacheAble(cacheInMinute = 30, cacheName = "USER_PERSIONAL_VECTOR", returnClass = PersonalizedSearch.class, cacheType = CacheType.SEARCH_REDIS, includeParams = { "uid" }) |
30 | + public PersonalizedSearch queryPersonalizedSearch(Map<String, String> paramMap) { | ||
28 | try { | 31 | try { |
29 | // 1、参数校验 | 32 | // 1、参数校验 |
30 | String uid = paramMap.get("uid"); | 33 | String uid = paramMap.get("uid"); |
@@ -41,7 +44,11 @@ public class PersonalVectorFeatureSearch { | @@ -41,7 +44,11 @@ public class PersonalVectorFeatureSearch { | ||
41 | if (StringUtils.isEmpty(userVectorFeature)) { | 44 | if (StringUtils.isEmpty(userVectorFeature)) { |
42 | return null; | 45 | return null; |
43 | } | 46 | } |
44 | - return new PersonalizedSearch(uid, vectorFeatureVersion, userVectorFeature); | 47 | + List<Double> doubleList = ConvertUtils.stringToDoubleList(userVectorFeature,","); |
48 | + if(CollectionUtils.isEmpty(doubleList)){ | ||
49 | + return null; | ||
50 | + } | ||
51 | + return new PersonalizedSearch(uid, vectorFeatureVersion, doubleList); | ||
45 | } catch (Exception e) { | 52 | } catch (Exception e) { |
46 | logger.error(e.getMessage(),e); | 53 | logger.error(e.getMessage(),e); |
47 | return null; | 54 | return null; |
-
Please register or login to post a comment