SceneRecallService.java 5.53 KB
package com.yoho.search.recall.scene;

import com.alibaba.fastjson.JSONObject;
import com.yoho.search.base.utils.CollectionUtils;
import com.yoho.search.base.utils.ISearchConstants;
import com.yoho.search.base.utils.ProductIndexEsField;
import com.yoho.search.core.es.model.SearchParam;
import com.yoho.search.core.es.model.SearchResult;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.recall.scene.component.*;
import com.yoho.search.recall.scene.strategy.helper.SortBuilderHelper;
import com.yoho.search.recall.scene.models.*;
import com.yoho.search.recall.scene.builder.request.RecallParamsBuilder;
import com.yoho.search.service.base.SearchCommonService;
import com.yoho.search.service.base.index.ProductIndexBaseService;
import com.yoho.search.service.helper.SearchCommonHelper;
import org.apache.commons.collections.MapUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
public class SceneRecallService {

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

    @Autowired
    private RecallParamsBuilder recallParamsBuilder;
    @Autowired
    private SearchCommonHelper searchCommonHelper;
    @Autowired
    private ProductIndexBaseService productIndexBaseService;
    @Autowired
    private SearchCommonService searchCommonService;
    @Autowired
    private BacthSknInfoComponent bacthSknInfoComponent;
    @Autowired
    private RecallService recallService;


    public SearchApiResult sceneRecall(Map<String, String> paramMap) {
        try {
            //1、分页参数验证
            int page = MapUtils.getIntValue(paramMap, "page", 1);
            int pageSize = MapUtils.getIntValue(paramMap, "viewNum", 20);
            if (page < 1 || pageSize < 0 || page * pageSize > 1000000) {
                return new SearchApiResult().setCode(400).setMessage("分页参数不合法");
            }
            //2、构造召回相关参数
            RecallSknParams recallSknParams = recallParamsBuilder.buildRecallParams(paramMap,pageSize);
            //3、执行召回
            RecallSknResult recallSknResult = recallService.getRecallSknResult(recallSknParams);
            //4、根据召回结果查询商品信息
            List<Map<String, Object>> productList = this.queryProductList(recallSknParams, recallSknResult,page,pageSize);
            //6、构造返回结果
            JSONObject dataMap = new JSONObject();
            dataMap.put("total", recallSknResult.getTotal());
            dataMap.put("page", page);
            dataMap.put("page_size", recallSknParams.getPageSize());
            dataMap.put("page_total", searchCommonHelper.getTotalPage(recallSknResult.getTotal(), recallSknParams.getPageSize()));
            dataMap.put("product_list", productList);
            return new SearchApiResult().setData(dataMap);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return new SearchApiResult().setData(null).setCode(500).setMessage("Exception");
        }
    }

    private List<Map<String, Object>> queryProductList(RecallSknParams recallSknParams, RecallSknResult recallSknResult,int page,int pageSize) {
        //1、判断当前页码是否在召回的页码里
        int recallTotalPage = recallSknResult.getRecallTotalPage();
        //2、在召回结果中则直接根据skn去查询
        if(page<=recallTotalPage){
            List<Integer> productSkns = CollectionUtils.safeSubList(recallSknResult.getSknList(),(page-1)*pageSize,page*pageSize);
            return bacthSknInfoComponent.queryProductListBySkn(productSkns,productSkns.size());
        }
        //3、过滤召回的skn,修改真实页码,执行查询
        int realPage = page - recallTotalPage;
        return this.queryProductByFilterSkn(recallSknResult.getSknList(), realPage, pageSize);
    }

    /**
     * 过滤掉已召回的skn,并按人气排序
     * @param notProductSkns
     * @param realPage
     * @param pageSize
     * @return
     */
    private List<Map<String, Object>> queryProductByFilterSkn(List<Integer> notProductSkns,int realPage,int pageSize){
        SearchParam searchParam = new SearchParam();
        //设置分页参数
        searchParam.setOffset((realPage-1)*pageSize);
        searchParam.setSize(pageSize);

        //设置filter
        BoolQueryBuilder filter = QueryBuilders.boolQuery();
        filter.mustNot(QueryBuilders.termsQuery(ProductIndexEsField.productSkn,notProductSkns));

        //设置IncludeFields
        searchParam.setIncludeFields(productIndexBaseService.getProductIndexIncludeFields());

        //设置排序
        List<SortBuilder<?>> sortBuilders = new ArrayList<>();
        sortBuilders.add(SortBuilderHelper.getHeatValueDescSort());
        sortBuilders.add(SortBuilderHelper.getSevendayMoneyDescSort());
        sortBuilders.add(SortBuilderHelper.getIdDescSort());
        searchParam.setSortBuilders(sortBuilders);
        SearchResult searchResult = searchCommonService.doSearch(ISearchConstants.INDEX_NAME_PRODUCT_INDEX,searchParam);
        return productIndexBaseService.getProductListWithPricePlan(searchResult.getResultList());
    }

}