...
|
...
|
@@ -20,12 +20,13 @@ import com.yoho.search.models.aggregations.AggKeyCount; |
|
|
import com.yoho.search.models.aggregations.AggKeyCountTwoLevel;
|
|
|
import com.yoho.search.service.aggregations.AggregationsService;
|
|
|
import com.yoho.search.service.aggregations.impls.ProductAnalysisDateAggregation;
|
|
|
import com.yoho.search.service.aggregations.impls.ProductAnalysisShopAggregation;
|
|
|
import com.yoho.search.service.aggregations.impls.ProductAnalysisBrandAggregation;
|
|
|
import com.yoho.search.service.aggregations.impls.ProductAnalysisSortAggregation;
|
|
|
import com.yoho.search.service.aggregations.impls.ShopBrandAggregation;
|
|
|
import com.yoho.search.service.aggregations.impls.BrandShopAggregation;
|
|
|
import com.yoho.search.service.helper.SearchParamHelper;
|
|
|
import com.yoho.search.service.recall.beans.persional.UserPersionalFactorComponent;
|
|
|
import com.yoho.search.service.recall.beans.vector.BrandVectorCacheBean;
|
|
|
import com.yoho.search.service.recall.config.SpecialShopConstants;
|
|
|
import com.yoho.search.service.scene.activity.recommendshop.ActivityShopBrand;
|
|
|
import com.yoho.search.service.scene.general.SortGroupService;
|
|
|
import org.apache.commons.collections.MapUtils;
|
...
|
...
|
@@ -182,8 +183,6 @@ public class RecommendOnProductAnalysisService { |
|
|
}
|
|
|
|
|
|
private List<Integer> getSeenShops(Map<String, String> paramMap) {
|
|
|
Map<String, String> paramMapClone = new HashMap<>();
|
|
|
paramMapClone.putAll(paramMap);
|
|
|
List<Integer> seenShopIds = new ArrayList<>();
|
|
|
try {
|
|
|
int uid = MapUtils.getIntValue(paramMap, "uid", 0);
|
...
|
...
|
@@ -193,9 +192,13 @@ public class RecommendOnProductAnalysisService { |
|
|
if (userFactor != null && !CollectionUtils.isEmpty(userFactor.getRealTimeSortBrandList())) {
|
|
|
List<Integer> realTimeBrandIds = userFactor.getRealTimeSortBrandList().stream().map(SortBrand::getBrandId).collect(Collectors.toList());
|
|
|
if (!CollectionUtils.isEmpty(realTimeBrandIds)) {
|
|
|
paramMapClone.put(SearchRequestParams.PARAM_SEARCH_BRAND, StringUtils.join(realTimeBrandIds, ","));
|
|
|
addDefaultParamsToParamMap(paramMapClone);
|
|
|
seenShopIds = aggShopId(paramMapClone, 10);
|
|
|
List<AggKeyCountTwoLevel> aggKeyCountTwoLevels = productAggBrandShopIds(paramMap, 10000, 20);
|
|
|
List<ActivityShopBrand> shopBrands = doCombineShopIdAndBrandId(aggKeyCountTwoLevels, realTimeBrandIds);
|
|
|
if (CollectionUtils.isEmpty(shopBrands)) {
|
|
|
return seenShopIds;
|
|
|
}
|
|
|
seenShopIds = shopBrands.stream().map(ActivityShopBrand::getShopId).distinct().collect(Collectors.toList());
|
|
|
return SearchCollectionUtils.safeSubList(seenShopIds, 0, 10);
|
|
|
}
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -205,53 +208,40 @@ public class RecommendOnProductAnalysisService { |
|
|
return seenShopIds;
|
|
|
}
|
|
|
|
|
|
|
|
|
private List<Integer> aggShopId(Map<String, String> paramMap, int aggCount) throws Exception{
|
|
|
List<Integer> seenShopIds = new ArrayList<>();
|
|
|
JSONObject aggResult = aggregationsService.getShopAggregationResult(paramMap, aggCount);
|
|
|
if (aggResult != null && !CollectionUtils.isEmpty(aggResult.getJSONArray("shopAgg"))) {
|
|
|
JSONArray shopList = aggResult.getJSONArray("shopAgg");
|
|
|
for (Object shop : shopList) {
|
|
|
seenShopIds.add(((JSONObject)shop).getInteger("shop_id"));
|
|
|
}
|
|
|
}
|
|
|
return seenShopIds;
|
|
|
}
|
|
|
|
|
|
private List<Integer> getRecommendShopWithPersonal(Map<String, String> paramMap, int viewNum, int uid, String udid) throws Exception{
|
|
|
List<Integer> recShopIds = new ArrayList<>();
|
|
|
SearchParam searchParam = buildSearchParam(paramMap);
|
|
|
List<Integer> aggBestShopIds = aggBestShopIds(searchParam, 1000);
|
|
|
addDefaultParamsToParamMap(paramMap);
|
|
|
SearchParam searchParam2 = searchParamHelper.buildDefault(paramMap);
|
|
|
List<AggKeyCountTwoLevel> aggKeyCountTwoLevels = productAggShopBrandIds(searchParam2, 100000, 200);
|
|
|
List<ActivityShopBrand> shopBrands = combineShopIdAndBrandId(aggKeyCountTwoLevels, aggBestShopIds, viewNum);
|
|
|
List<Integer> aggBestBrandIds = aggBestBrandIds(searchParam, 1000);
|
|
|
List<AggKeyCountTwoLevel> aggKeyCountTwoLevels = productAggBrandShopIds(paramMap, 10000, 100);
|
|
|
List<ActivityShopBrand> shopBrands = combineShopIdAndBrandId(aggKeyCountTwoLevels, aggBestBrandIds, viewNum + 10);
|
|
|
if (CollectionUtils.isEmpty(shopBrands)) {
|
|
|
return recShopIds;
|
|
|
}
|
|
|
recShopIds = shopBrands.stream().map(ActivityShopBrand::getShopId).collect(Collectors.toList());
|
|
|
if (uid > 0 || StringUtils.isNotBlank(udid)) {
|
|
|
recShopIds = reorderShopOnUserPersonalBrand(shopBrands, aggKeyCountTwoLevels, uid, udid);
|
|
|
}
|
|
|
recShopIds = reorderShopOnUserPersonalBrand(shopBrands, aggKeyCountTwoLevels, uid, udid);
|
|
|
return SearchCollectionUtils.safeSubList(recShopIds, 0, viewNum);
|
|
|
}
|
|
|
|
|
|
//从yoho_product_analysis聚合卖的最好的shopId
|
|
|
private List<Integer> aggBestShopIds(SearchParam searchParam, int shopSize) throws Exception {
|
|
|
IAggregation aggregation = new ProductAnalysisShopAggregation(shopSize);
|
|
|
private List<Integer> aggBestBrandIds(SearchParam searchParam, int shopSize) throws Exception {
|
|
|
IAggregation aggregation = new ProductAnalysisBrandAggregation(shopSize);
|
|
|
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
|
|
|
JSONObject jsonObject = aggregationsService.getAggNameAndResponseWithCache(aggregation, searchParam, ISearchConstants.INDEX_NAME_YOHO_PRODUCT_ANALYSIS);
|
|
|
List<Integer> aggShopIds = new ArrayList<>();
|
|
|
List<Integer> aggBrandIds = new ArrayList<>();
|
|
|
if (jsonObject != null && jsonObject.get(aggregation.aggName()) != null) {
|
|
|
aggShopIds = JSON.parseArray(JSON.toJSONString(jsonObject.get(aggregation.aggName())), Integer.class);
|
|
|
aggBrandIds = JSON.parseArray(JSON.toJSONString(jsonObject.get(aggregation.aggName())), Integer.class);
|
|
|
}
|
|
|
return aggShopIds;
|
|
|
return aggBrandIds;
|
|
|
}
|
|
|
|
|
|
|
|
|
//从pi聚合所有的的shopId
|
|
|
private List<AggKeyCountTwoLevel> productAggShopBrandIds(SearchParam searchParam, int shopSize, int brandSize) throws Exception {
|
|
|
IAggregation aggregation = new ShopBrandAggregation(shopSize, brandSize);
|
|
|
private List<AggKeyCountTwoLevel> productAggBrandShopIds(Map<String, String> paramMap, int brandSize, int shopSize) throws Exception {
|
|
|
Map<String, String> paramMapDefault = new HashMap<>();
|
|
|
if (StringUtils.isNotBlank(paramMap.get(SearchRequestParams.PARAM_SEARCH_SHELVETIME))) {
|
|
|
paramMapDefault.put(SearchRequestParams.PARAM_SEARCH_SHELVETIME, paramMap.get(SearchRequestParams.PARAM_SEARCH_SHELVETIME));
|
|
|
}
|
|
|
addDefaultParamsToParamMap(paramMapDefault);
|
|
|
SearchParam searchParam = searchParamHelper.buildDefault(paramMapDefault);
|
|
|
IAggregation aggregation = new BrandShopAggregation(brandSize, shopSize);
|
|
|
searchParam.setAggregationBuilders(Arrays.asList(aggregation.getBuilder()));
|
|
|
JSONObject jsonObject = aggregationsService.getAggNameAndResponseWithCache(aggregation, searchParam);
|
|
|
List<AggKeyCountTwoLevel> aggKeyCountTwoLevels = new ArrayList<>();
|
...
|
...
|
@@ -263,33 +253,40 @@ public class RecommendOnProductAnalysisService { |
|
|
|
|
|
|
|
|
//构造卖的最好的shopidbrandid
|
|
|
private List<ActivityShopBrand> combineShopIdAndBrandId(List<AggKeyCountTwoLevel> aggKeyCountTwoLevels, List<Integer> bestShopIds, int viewNum){
|
|
|
private List<ActivityShopBrand> combineShopIdAndBrandId(List<AggKeyCountTwoLevel> aggKeyCountTwoLevels, List<Integer> aggBestBrandIds, int size){
|
|
|
if (CollectionUtils.isEmpty(aggKeyCountTwoLevels)) {
|
|
|
return Collections.emptyList();
|
|
|
}
|
|
|
List<AggKeyCountTwoLevel> intersection = getCandidateShopBrands(aggKeyCountTwoLevels, bestShopIds, viewNum);
|
|
|
List<Integer> realBestShopIds = intersection.stream().map(e -> e.getFirstAggKeyCount().getKey()).collect(Collectors.toList());
|
|
|
List<AggKeyCountTwoLevel> candidateBrandShops = getCandidateBrandShops(aggKeyCountTwoLevels, aggBestBrandIds, size);
|
|
|
if (CollectionUtils.isEmpty(candidateBrandShops)) {
|
|
|
return Collections.emptyList();
|
|
|
}
|
|
|
List<Integer> realBestBrandIds = candidateBrandShops.stream().map(e -> e.getFirstAggKeyCount().getKey()).collect(Collectors.toList());
|
|
|
return doCombineShopIdAndBrandId(candidateBrandShops, realBestBrandIds);
|
|
|
}
|
|
|
|
|
|
private List<ActivityShopBrand> doCombineShopIdAndBrandId(List<AggKeyCountTwoLevel> candidateBrandShops, List<Integer> realBestBrandIds){
|
|
|
List<ActivityShopBrand> shopBrandList = new ArrayList<>();
|
|
|
Set<Integer> filterBrandIds = new HashSet<>();
|
|
|
if (!CollectionUtils.isEmpty(intersection) && !CollectionUtils.isEmpty(realBestShopIds)) {
|
|
|
Map<Integer, AggKeyCountTwoLevel> intersectionMap = intersection.stream().collect(Collectors.toMap(i -> i.getFirstAggKeyCount().getKey(), p -> p));
|
|
|
for (Integer shopId : realBestShopIds) {
|
|
|
if (shopId.equals(0)) {
|
|
|
Set<Integer> filterShopIds = new HashSet<>();
|
|
|
if (!CollectionUtils.isEmpty(candidateBrandShops) && !CollectionUtils.isEmpty(realBestBrandIds)) {
|
|
|
Map<Integer, AggKeyCountTwoLevel> andidateBrandShopsMap = candidateBrandShops.stream().collect(Collectors.toMap(i -> i.getFirstAggKeyCount().getKey(), p -> p));
|
|
|
for (Integer brandId : realBestBrandIds) {
|
|
|
if (brandId.equals(0)) {
|
|
|
continue;
|
|
|
}
|
|
|
AggKeyCountTwoLevel aggKeyCountTwoLevel = intersectionMap.get(shopId);
|
|
|
AggKeyCountTwoLevel aggKeyCountTwoLevel = andidateBrandShopsMap.get(brandId);
|
|
|
if (aggKeyCountTwoLevel != null) {
|
|
|
List<AggKeyCount> secondList = aggKeyCountTwoLevel.getSecondAggKeyCountList();
|
|
|
for (AggKeyCount brandAggKeyCount : secondList) {
|
|
|
Integer brandId = brandAggKeyCount.getKey();
|
|
|
if (brandId.equals(0)) {
|
|
|
for (AggKeyCount shopAggKeyCount : secondList) {
|
|
|
Integer shopId = shopAggKeyCount.getKey();
|
|
|
if (shopId.equals(0)) {
|
|
|
continue;
|
|
|
}
|
|
|
if (filterBrandIds.contains(brandId)) {
|
|
|
if (filterShopIds.contains(shopId)) {
|
|
|
continue;
|
|
|
}
|
|
|
shopBrandList.add(new ActivityShopBrand(shopId, brandId));//取商品数最多的一个店铺即可,防止多品店的问题
|
|
|
filterBrandIds.add(brandId);//每个品牌只赋给一个店铺
|
|
|
filterShopIds.add(shopId);//每个品牌只赋给一个店铺
|
|
|
break;
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -298,18 +295,18 @@ public class RecommendOnProductAnalysisService { |
|
|
return shopBrandList;
|
|
|
}
|
|
|
|
|
|
private List<AggKeyCountTwoLevel> getCandidateShopBrands(List<AggKeyCountTwoLevel> aggKeyCountTwoLevels, List<Integer> bestShopIds, int viewNum) {
|
|
|
|
|
|
private List<AggKeyCountTwoLevel> getCandidateBrandShops(List<AggKeyCountTwoLevel> aggKeyCountTwoLevels, List<Integer> aggBestBrandIds, int candidateNum) {
|
|
|
List<AggKeyCountTwoLevel> candidates = new ArrayList<>();
|
|
|
int candidateNum = 1000;
|
|
|
if (CollectionUtils.isEmpty(bestShopIds)) {
|
|
|
if (CollectionUtils.isEmpty(aggBestBrandIds)) {
|
|
|
candidates = SearchCollectionUtils.safeSubList(aggKeyCountTwoLevels, 0, candidateNum);
|
|
|
}else {
|
|
|
List<AggKeyCountTwoLevel> filtered = aggKeyCountTwoLevels.stream().filter(e -> bestShopIds.contains(e.getFirstAggKeyCount().getKey())).collect(Collectors.toList());
|
|
|
List<AggKeyCountTwoLevel> filtered = aggKeyCountTwoLevels.stream().filter(e -> aggBestBrandIds.contains(e.getFirstAggKeyCount().getKey())).collect(Collectors.toList());
|
|
|
if (!CollectionUtils.isEmpty(filtered)) {
|
|
|
Map<Integer, AggKeyCountTwoLevel> filteredMap = filtered.stream().collect(Collectors.toMap(i -> i.getFirstAggKeyCount().getKey(), p -> p));
|
|
|
for (Integer shopId : bestShopIds) {
|
|
|
if (filteredMap.get(shopId) != null) {
|
|
|
candidates.add(filteredMap.get(shopId));
|
|
|
for (Integer brandId : aggBestBrandIds) {
|
|
|
if (filteredMap.get(brandId) != null) {
|
|
|
candidates.add(filteredMap.get(brandId));
|
|
|
}
|
|
|
}
|
|
|
}
|
...
|
...
|
@@ -326,23 +323,24 @@ public class RecommendOnProductAnalysisService { |
|
|
|
|
|
//获取用户有行为的品类 排序sort, RealTimeSort加分放前面,预测的放后面
|
|
|
private List<Integer> reorderShopOnUserPersonalBrand(List<ActivityShopBrand> shopBrands, List<AggKeyCountTwoLevel> aggKeyCountTwoLevels, int uid, String udid) {
|
|
|
List<Integer> aggBestShopIds = shopBrands.stream().map(ActivityShopBrand::getShopId).collect(Collectors.toList());
|
|
|
UserPersonalFactorRspNew userFactor = getUserPersonalFactor(uid, udid);
|
|
|
if (userFactor != null && !CollectionUtils.isEmpty(userFactor.getRealTimeSortBrandList())) {
|
|
|
if (!CollectionUtils.isEmpty(userFactor.getBrandVectorW2v())) {
|
|
|
calScore(shopBrands, userFactor.getBrandVectorW2v(), false);
|
|
|
} else {
|
|
|
calScore(shopBrands, userFactor.getBrandVector(), true);
|
|
|
if (uid > 0 || StringUtils.isNotBlank(udid)) {
|
|
|
UserPersonalFactorRspNew userFactor = getUserPersonalFactor(uid, udid);
|
|
|
if (userFactor != null && !CollectionUtils.isEmpty(userFactor.getRealTimeSortBrandList())) {
|
|
|
if (!CollectionUtils.isEmpty(userFactor.getBrandVectorW2v())) {
|
|
|
calScore(shopBrands, userFactor.getBrandVectorW2v(), false);
|
|
|
} else {
|
|
|
calScore(shopBrands, userFactor.getBrandVector(), true);
|
|
|
}
|
|
|
Collections.sort(shopBrands, (o1, o2) -> (o2.getScore()).compareTo(o1.getScore()));
|
|
|
List<Integer> orderedAggBestShopIds = shopBrands.stream().map(ActivityShopBrand::getShopId).collect(Collectors.toList());
|
|
|
List<Integer> personalBrandIds = userFactor.getRealTimeSortBrandList().stream().map(SortBrand::getBrandId).collect(Collectors.toList());
|
|
|
List<ActivityShopBrand> personalShopBrands = doCombineShopIdAndBrandId(aggKeyCountTwoLevels, personalBrandIds);
|
|
|
List<Integer> personalShopIds = personalShopBrands.stream().map(ActivityShopBrand::getShopId).collect(Collectors.toList());
|
|
|
personalShopIds.addAll(orderedAggBestShopIds);
|
|
|
return personalShopIds.stream().distinct().collect(Collectors.toList());
|
|
|
}
|
|
|
Collections.sort(shopBrands, (o1, o2) -> (o2.getScore()).compareTo(o1.getScore()));
|
|
|
List<Integer> orderedAggBestShopIds = shopBrands.stream().map(ActivityShopBrand::getShopId).collect(Collectors.toList());
|
|
|
List<Integer> personalBrandIds = userFactor.getRealTimeSortBrandList().stream().map(SortBrand::getBrandId).collect(Collectors.toList());
|
|
|
Map<Integer, Integer> brandId2ShopIdMap = shopBrands.stream().collect(Collectors.toMap(ActivityShopBrand::getBrandId, ActivityShopBrand::getShopId));
|
|
|
List<Integer> personalShopIds = personalBrandIds.stream().filter(e -> brandId2ShopIdMap.get(e) != null).map(e -> brandId2ShopIdMap.get(e)).distinct().collect(Collectors.toList());
|
|
|
personalShopIds.addAll(orderedAggBestShopIds);
|
|
|
return personalShopIds.stream().distinct().collect(Collectors.toList());
|
|
|
}
|
|
|
return aggBestShopIds;
|
|
|
return shopBrands.stream().map(ActivityShopBrand::getShopId).distinct().collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
/**
|
...
|
...
|
@@ -443,10 +441,15 @@ public class RecommendOnProductAnalysisService { |
|
|
|
|
|
//SearchParam
|
|
|
private SearchParam buildSearchParam(Map<String, String> paramMap) {
|
|
|
paramMap.put(SearchRequestParams.PARAM_SEARCH_NOT_SHOP_ID, SpecialShopConstants.JISHOU_SHOP_ID.toString());// 非寄售店铺
|
|
|
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
|
|
|
BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
|
|
|
addMustIntTermsQuery(boolFilter, paramMap, SearchRequestParams.PARAM_SEARCH_GENDER, ProductIndexEsField.gender);
|
|
|
addMustIntTermsQuery(boolFilter, paramMap, SearchRequestParams.PARAM_SEARCH_YH_CHANNEL, "yhChannel");
|
|
|
addMustIntTermsQuery(boolFilter, paramMap, SearchRequestParams.PARAM_SEARCH_MAXSORT, ProductIndexEsField.maxSortId);
|
|
|
addMustIntTermsQuery(boolFilter, paramMap, SearchRequestParams.PARAM_SEARCH_MIDDLESORT, ProductIndexEsField.middleSortId);
|
|
|
addMustIntTermsQuery(boolFilter, paramMap, SearchRequestParams.PARAM_SEARCH_SMALLSORT, ProductIndexEsField.smallSortId);
|
|
|
addMustNotIntTermsQuery(boolFilter,paramMap, SearchRequestParams.PARAM_SEARCH_NOT_SHOP_ID,ProductIndexEsField.shopId);
|
|
|
addMustDoubleRangeQuery(boolFilter, paramMap, SearchRequestParams.PARAM_SEARCH_SHELVETIME, ProductIndexEsField.shelveTime);
|
|
|
try {
|
|
|
List<String> day_date = dateRange.get("DAY_DATE");
|
...
|
...
|
@@ -475,6 +478,15 @@ public class RecommendOnProductAnalysisService { |
|
|
boolFilter.must(QueryBuilders.termsQuery(esField, values));
|
|
|
}
|
|
|
|
|
|
private void addMustNotIntTermsQuery(BoolQueryBuilder boolFilter,Map<String, String> paramMap, String paramName, String esField){
|
|
|
List<Integer> values = ConvertUtils.stringToIntList(paramMap.get(paramName), ",");
|
|
|
if(values==null || values.isEmpty()){
|
|
|
return;
|
|
|
}
|
|
|
boolFilter.mustNot(QueryBuilders.termsQuery(esField, values));
|
|
|
}
|
|
|
|
|
|
|
|
|
private void addMustDoubleRangeQuery(BoolQueryBuilder boolFilter, Map<String, String> paramMap, String paramName, String esField) {
|
|
|
List<Double> values = ConvertUtils.stringToDoubleList(paramMap.get(paramName), ",");
|
|
|
if (values == null || values.isEmpty() || values.size() != 2) {
|
...
|
...
|
@@ -490,6 +502,7 @@ public class RecommendOnProductAnalysisService { |
|
|
paramMap.put(SearchRequestParams.PARAM_SEARCH_SHOWSOLDOUT, "1");// 显示延期显示的商品
|
|
|
paramMap.put(SearchRequestParams.PARAM_SEARCH_ISOUTLETS, "2");// 非奥莱
|
|
|
paramMap.put(SearchRequestParams.PARAM_SEARCH_ATTRIBUTE_NOT, "2");// 非赠品
|
|
|
paramMap.put(SearchRequestParams.PARAM_SEARCH_NOT_SHOP_ID, SpecialShopConstants.JISHOU_SHOP_ID.toString());// 非寄售店铺
|
|
|
}
|
|
|
|
|
|
private void addShelveTime(Map<String, String> paramMap) {
|
...
|
...
|
|