|
|
package com.yoho.search.service.scene.general;
|
|
|
|
|
|
import java.util.Date;
|
|
|
import java.util.Map;
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.yoho.search.base.utils.DateUtil;
|
|
|
import com.yoho.search.base.utils.ISearchConstants;
|
|
|
import com.yoho.search.base.utils.ProductIndexEsField;
|
|
|
import com.yoho.search.cache.beans.AbstractCacheAbleService;
|
|
|
import com.yoho.search.cache.model.SearchCache;
|
|
|
import com.yoho.search.cache.CacheTimeConstants;
|
|
|
import com.yoho.search.cache.beans.AbstractCacheComponent;
|
|
|
import com.yoho.search.common.SearchCommonService;
|
|
|
import com.yoho.search.common.utils.SearchApiResultUtils;
|
|
|
import com.yoho.search.core.es.model.SearchParam;
|
|
|
import com.yoho.search.core.es.model.SearchResult;
|
|
|
import com.yoho.search.common.SearchCommonService;
|
|
|
import com.yoho.search.models.SearchApiResult;
|
|
|
import com.yoho.search.service.helper.SearchCommonHelper;
|
|
|
import com.yoho.search.service.helper.SearchParamHelper;
|
|
|
import com.yoho.search.service.recall.models.common.ParamQueryFilter;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.elasticsearch.action.search.SearchType;
|
|
|
import org.elasticsearch.index.query.BoolQueryBuilder;
|
|
|
|
|
|
import com.yoho.search.models.SearchApiResult;
|
|
|
import org.elasticsearch.index.query.QueryBuilder;
|
|
|
import org.elasticsearch.index.query.QueryBuilders;
|
|
|
import org.slf4j.Logger;
|
...
|
...
|
@@ -27,133 +23,157 @@ import org.slf4j.LoggerFactory; |
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
@Service
|
|
|
public class ProductCountService extends AbstractCacheAbleService {
|
|
|
|
|
|
private static final Logger Logger = LoggerFactory.getLogger(ProductCountService.class);
|
|
|
|
|
|
@Autowired
|
|
|
private SearchCommonService searchCommonService;
|
|
|
@Autowired
|
|
|
private SearchCommonHelper searchCommonHelper;
|
|
|
@Autowired
|
|
|
private SearchParamHelper searchParamHelper;
|
|
|
|
|
|
@Override
|
|
|
public SearchCache getSearchCache() {
|
|
|
return searchCacheFactory.getProductCountSearchCache();
|
|
|
}
|
|
|
|
|
|
private long queryProductCount(SearchParam searchParam) {
|
|
|
// 1)为searchParam设置默认值
|
|
|
searchParam.setAggregationBuilders(null);
|
|
|
searchParam.setSearchType(SearchType.QUERY_THEN_FETCH);
|
|
|
|
|
|
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
|
|
|
|
|
|
// 2) 先从缓存中获取,如果能取到,则直接返回
|
|
|
JSONObject jsonObject = searchCacheService.getJSONObjectFromCache(this.searchCache, ISearchConstants.INDEX_NAME_PRODUCT_INDEX, searchParam);
|
|
|
if (jsonObject != null) {
|
|
|
return jsonObject.getLongValue("total");
|
|
|
}
|
|
|
// 3) 执行检索
|
|
|
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
|
|
|
// 4) 构造返回结果
|
|
|
JSONObject result = new JSONObject();
|
|
|
long total = 0;
|
|
|
if (searchResult != null) {
|
|
|
total = searchResult.getTotal();
|
|
|
}
|
|
|
result.put("total", total);
|
|
|
searchCacheService.addJSONObjectToCache(this.searchCache, indexName, searchParam, result);
|
|
|
return total;
|
|
|
}
|
|
|
|
|
|
public SearchApiResult productCount(Map<String, String> paramMap) {
|
|
|
try {
|
|
|
Logger.info("[func=productCount][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
|
|
|
// 1)、构造通用参数
|
|
|
SearchParam searchParam = searchParamHelper.buildDefault(paramMap);
|
|
|
long count = this.queryProductCount(searchParam);
|
|
|
JSONObject result = new JSONObject();
|
|
|
result.put("total", count);
|
|
|
return new SearchApiResult().setData(result);
|
|
|
} catch (Exception e) {
|
|
|
return SearchApiResultUtils.errorSearchApiResult("productCount", paramMap, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public long countByQuery(Map<String, String> paramMap) {
|
|
|
try {
|
|
|
Logger.info("[func=countByQuery][param={}][begin={}]", paramMap.toString(), System.currentTimeMillis());
|
|
|
// 1)关键参数检测
|
|
|
String query = paramMap.get("query");
|
|
|
if (StringUtils.isBlank(query)) {
|
|
|
return 0;
|
|
|
}
|
|
|
// 2)默认的must_filter
|
|
|
BoolQueryBuilder mustFilter = QueryBuilders.boolQuery();
|
|
|
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));
|
|
|
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.attribute, 2));
|
|
|
mustFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.storageNum).gte(1));
|
|
|
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isOutlets, 2));
|
|
|
if (!searchCommonHelper.containGlobal(paramMap)) {
|
|
|
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
|
|
|
}
|
|
|
// 3、构造searchParam
|
|
|
SearchParam searchParam = searchParamHelper.buildWithMustFilter(paramMap, mustFilter);
|
|
|
return this.queryProductCount(searchParam);
|
|
|
} catch (Exception e) {
|
|
|
Logger.error(e.getMessage(), e);
|
|
|
return 0L;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private BoolQueryBuilder genScoreDefaultFilter() {
|
|
|
BoolQueryBuilder mustFilter = QueryBuilders.boolQuery();
|
|
|
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));
|
|
|
mustFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.storageNum).gte(10));
|
|
|
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isOutlets, 2));
|
|
|
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.attribute, 2));
|
|
|
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
|
|
|
return mustFilter;
|
|
|
}
|
|
|
|
|
|
private long queryCount(QueryBuilder paramFilter, BoolQueryBuilder scoreFilter) {
|
|
|
BoolQueryBuilder filter = new BoolQueryBuilder();
|
|
|
filter.must(paramFilter);
|
|
|
filter.must(scoreFilter);
|
|
|
SearchParam searchParam = new SearchParam();
|
|
|
searchParam.setFiter(filter);
|
|
|
return this.queryProductCount(searchParam);
|
|
|
}
|
|
|
|
|
|
public BoolQueryBuilder genScoreFilter(BoolQueryBuilder paramFilter) {
|
|
|
BoolQueryBuilder scoreFilter = this.genScoreDefaultFilter();
|
|
|
long totalCount = this.queryCount(paramFilter, scoreFilter);
|
|
|
if (totalCount <= 2000) {
|
|
|
return scoreFilter;
|
|
|
}
|
|
|
// 零点那一刻命中不了,得想办法解决【比如凌晨两点再切数量】
|
|
|
long todayLastTimeSecond = DateUtil.getLastTimeSecond(new Date());
|
|
|
long oneMonthInSecond = 30 * 24 * 60 * 60;
|
|
|
int tryCount = 1;
|
|
|
while (tryCount <= 3) {
|
|
|
scoreFilter = this.genScoreDefaultFilter();
|
|
|
scoreFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.firstShelveTime).from(todayLastTimeSecond - tryCount * oneMonthInSecond));
|
|
|
totalCount = this.queryCount(paramFilter, scoreFilter);
|
|
|
if (totalCount >= 1000) {
|
|
|
return scoreFilter;
|
|
|
}
|
|
|
tryCount++;
|
|
|
}
|
|
|
return scoreFilter;
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
long todayLastTimeSecond = DateUtil.getLastTimeSecond(new Date());
|
|
|
long oneMonthInSecond = 30 * 24 * 60 * 60;
|
|
|
System.out.println(todayLastTimeSecond - 1 * oneMonthInSecond);
|
|
|
}
|
|
|
import java.util.Date;
|
|
|
import java.util.Map;
|
|
|
|
|
|
@Service
|
|
|
public class ProductCountService extends AbstractCacheComponent<Long> {
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(ProductCountService.class);
|
|
|
|
|
|
@Autowired
|
|
|
private SearchCommonService searchCommonService;
|
|
|
@Autowired
|
|
|
private SearchCommonHelper searchCommonHelper;
|
|
|
@Autowired
|
|
|
private SearchParamHelper searchParamHelper;
|
|
|
|
|
|
/**
|
|
|
* 获取商品数量
|
|
|
*
|
|
|
* @param paramMap
|
|
|
* @return
|
|
|
*/
|
|
|
public SearchApiResult productCount(Map<String, String> paramMap) {
|
|
|
try {
|
|
|
// 1、构造ParamQueryFilter
|
|
|
ParamQueryFilter paramQueryFilter = searchParamHelper.buildParamQueryFilter(paramMap);
|
|
|
// 2、执行查询
|
|
|
Long count = super.queryWithCache(paramQueryFilter, paramMap);
|
|
|
long countValue = count == null ? 0 : count.longValue();
|
|
|
//3、构造返回结果
|
|
|
JSONObject result = new JSONObject();
|
|
|
result.put("total", count);
|
|
|
return new SearchApiResult().setData(result);
|
|
|
} catch (Exception e) {
|
|
|
return SearchApiResultUtils.errorSearchApiResult(logger, paramMap, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据query查询商品数量,并添加一些默认的条件
|
|
|
*
|
|
|
* @param paramMap
|
|
|
* @return
|
|
|
*/
|
|
|
public long countByQuery(Map<String, String> paramMap) {
|
|
|
try {
|
|
|
// 1、关键参数检测
|
|
|
String query = paramMap.get("query");
|
|
|
if (StringUtils.isBlank(query)) {
|
|
|
return 0;
|
|
|
}
|
|
|
// 2、构造ParamQueryFilter
|
|
|
BoolQueryBuilder mustFilter = QueryBuilders.boolQuery();
|
|
|
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));
|
|
|
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.attribute, 2));
|
|
|
mustFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.storageNum).gte(1));
|
|
|
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isOutlets, 2));
|
|
|
if (!searchCommonHelper.containGlobal(paramMap)) {
|
|
|
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
|
|
|
}
|
|
|
ParamQueryFilter paramQueryFilter = searchParamHelper.buildParamQueryFilter(paramMap, mustFilter);
|
|
|
|
|
|
// 3、执行查询
|
|
|
Long count = super.queryWithCache(paramQueryFilter, paramMap);
|
|
|
|
|
|
// 4、返回结果
|
|
|
return count == null ? 0 : count.longValue();
|
|
|
} catch (Exception e) {
|
|
|
logger.error(e.getMessage(), e);
|
|
|
return 0L;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* 根据当前的查询条件,生成额外的过滤器--模糊搜索向量计算圈定范围时使用
|
|
|
*
|
|
|
* @param paramFilter
|
|
|
* @return
|
|
|
*/
|
|
|
public BoolQueryBuilder genScoreFilter(BoolQueryBuilder paramFilter) {
|
|
|
BoolQueryBuilder scoreFilter = this.genScoreDefaultFilter();
|
|
|
long totalCount = this.queryCountWithScoreFilter(paramFilter, scoreFilter);
|
|
|
if (totalCount <= 2000) {
|
|
|
return scoreFilter;
|
|
|
}
|
|
|
// 零点那一刻命中不了,得想办法解决【比如凌晨两点再切数量】
|
|
|
long todayLastTimeSecond = DateUtil.getLastTimeSecond(new Date());
|
|
|
long oneMonthInSecond = 30 * 24 * 60 * 60;
|
|
|
int tryCount = 1;
|
|
|
while (tryCount <= 3) {
|
|
|
scoreFilter = this.genScoreDefaultFilter();
|
|
|
scoreFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.firstShelveTime).from(todayLastTimeSecond - tryCount * oneMonthInSecond));
|
|
|
totalCount = this.queryCountWithScoreFilter(paramFilter, scoreFilter);
|
|
|
if (totalCount >= 1000) {
|
|
|
return scoreFilter;
|
|
|
}
|
|
|
tryCount++;
|
|
|
}
|
|
|
return scoreFilter;
|
|
|
}
|
|
|
|
|
|
private BoolQueryBuilder genScoreDefaultFilter() {
|
|
|
BoolQueryBuilder mustFilter = QueryBuilders.boolQuery();
|
|
|
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.status, 1));
|
|
|
mustFilter.must(QueryBuilders.rangeQuery(ProductIndexEsField.storageNum).gte(10));
|
|
|
mustFilter.must(QueryBuilders.termQuery(ProductIndexEsField.isOutlets, 2));
|
|
|
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.attribute, 2));
|
|
|
mustFilter.mustNot(QueryBuilders.termQuery(ProductIndexEsField.isGlobal, "Y"));
|
|
|
return mustFilter;
|
|
|
}
|
|
|
|
|
|
private long queryCountWithScoreFilter(QueryBuilder paramFilter, BoolQueryBuilder scoreFilter) {
|
|
|
try {
|
|
|
//1、构建ParamQueryFilter
|
|
|
BoolQueryBuilder filter = new BoolQueryBuilder();
|
|
|
filter.must(paramFilter);
|
|
|
filter.must(scoreFilter);
|
|
|
ParamQueryFilter paramQueryFilter = new ParamQueryFilter(QueryBuilders.matchAllQuery(), filter);
|
|
|
|
|
|
// 2、执行查询
|
|
|
Long count = super.queryWithCache(paramQueryFilter, null);
|
|
|
|
|
|
// 3、返回结果
|
|
|
return count == null ? 0 : count.longValue();
|
|
|
} catch (Exception e) {
|
|
|
logger.error(e.getMessage(), e);
|
|
|
return 0L;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected Long doRealQuery(ParamQueryFilter paramQueryFilter, Map<String, String> paramMap) throws Exception {
|
|
|
// 1、构造SearchParam
|
|
|
SearchParam searchParam = searchParamHelper.buildSearchParam(paramQueryFilter);
|
|
|
searchParam.setSize(0);
|
|
|
|
|
|
// 2、 执行检索
|
|
|
final String indexName = ISearchConstants.INDEX_NAME_PRODUCT_INDEX;
|
|
|
SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
|
|
|
|
|
|
// 3、 构造返回结果
|
|
|
return searchResult == null ? 0 : searchResult.getTotal();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected int cacheTimeInMinute() {
|
|
|
return CacheTimeConstants.CACHE_15_MINUTE;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected String cacheSceneKey() {
|
|
|
return "PRODUCT_COUNT";
|
|
|
}
|
|
|
} |
...
|
...
|
|