Просмотр исходного кода

增加批次信息统计接口

sunyj 8 лет назад
Родитель
Сommit
af90ac4bda

+ 31 - 0
search-api/src/main/java/com/uas/search/model/CollectField.java

@@ -0,0 +1,31 @@
+package com.uas.search.model;
+
+/**
+ * 统计信息时需要的字段
+ * 
+ * @author sunyj
+ * @since 2017年7月12日 上午9:03:29
+ */
+public enum CollectField {
+
+	// 批次统计
+	/**
+	 * 类目
+	 */
+	GOODS_KIND,
+
+	/**
+	 * 品牌
+	 */
+	GOODS_BRAND,
+
+	/**
+	 * 货源
+	 */
+	GOODS_STORE_TYPE,
+
+	/**
+	 * 货币
+	 */
+	GOODS_CRNAME;
+}

+ 31 - 0
search-api/src/main/java/com/uas/search/service/SearchService.java

@@ -5,7 +5,9 @@ import java.util.Map;
 import java.util.Set;
 
 import com.uas.search.exception.SearchException;
+import com.uas.search.model.CollectField;
 import com.uas.search.model.PageParams;
+import com.uas.search.model.PageParams.FilterField;
 
 /**
  * 搜索服务的接口
@@ -223,4 +225,33 @@ public interface SearchService {
 	 */
 	public Map<String, Object> getGoodsIds(String keyword, PageParams pageParams) throws SearchException;
 
+	/**
+	 * 搜索批次时,统计指定信息
+	 * 
+	 * @param keyword
+	 *            关键词
+	 * @param collectedField
+	 *            需要统计的信息
+	 * @param filters
+	 *            过滤条件,值的类型由键决定:
+	 * 
+	 *            <PRE>
+	 *            GOODS_KINDID: Long
+	 *            GOODS_BRANDID: Long
+	 *            GOODS_STORE_TYPE: String
+	 *            GOODS_CRNAME: String
+	 *            </PRE>
+	 * 
+	 * @return 统计的信息(由collectedField决定)
+	 * 
+	 *         <PRE>
+	 *            GOODS_KIND: ki_id、ki_name_cn
+	 *            GOODS_BRAND: br_id、br_uuid、br_name_cn、br_name_en
+	 *            GOODS_STORE_TYPE: store_type
+	 *            GOODS_CRNAME: cr_name
+	 *         </PRE>
+	 */
+	public List<Map<String, Object>> collectBySearchGoods(String keyword, CollectField collectedField,
+			Map<FilterField, Object> filters);
+
 }

+ 24 - 0
search-console/src/main/java/com/uas/search/console/controller/SearchController.java

@@ -21,8 +21,10 @@ import com.uas.search.console.core.util.ContextUtils;
 import com.uas.search.console.dao.ComponentSimpleInfoDao;
 import com.uas.search.console.model.BrandSimpleInfo;
 import com.uas.search.console.model.ComponentSimpleInfo;
+import com.uas.search.console.model.GoodsSimpleInfo;
 import com.uas.search.console.model.KindSimpleInfo;
 import com.uas.search.console.service.InnerSearchService;
+import com.uas.search.model.CollectField;
 import com.uas.search.model.PageParams;
 import com.uas.search.model.PageParams.FilterField;
 import com.uas.search.model.Sort;
@@ -217,6 +219,22 @@ public class SearchController {
 		return searchService.getGoodsIds(keyword, pageParams);
 	}
 
+	@RequestMapping("/collectBySearchGoods")
+	@ResponseBody
+	public List<Map<String, Object>> collectBySearchGoods(String keyword, String collectedField, String filters) {
+		Map<FilterField, Object> filtersMap = new HashMap<>();
+		if (!StringUtils.isEmpty(filters)) {
+			JSONObject json = JSONObject.parseObject(filters);
+			Set<Entry<String, Object>> entrySet = json.entrySet();
+			for (Entry<String, Object> entry : entrySet) {
+				FilterField field = FilterField.valueOf(entry.getKey());
+				filtersMap.put(field, entry.getValue());
+			}
+		}
+		return searchService.collectBySearchGoods(keyword, CollectField.valueOf(collectedField.toUpperCase()),
+				filtersMap);
+	}
+
 	@RequestMapping("/kind/{id}")
 	@ResponseBody
 	public KindSimpleInfo getKind(@PathVariable Long id) {
@@ -234,4 +252,10 @@ public class SearchController {
 	public ComponentSimpleInfo getComponent(@PathVariable Long id) {
 		return innerSearchService.getComponent(id);
 	}
+
+	@RequestMapping("/goods/{id}")
+	@ResponseBody
+	public GoodsSimpleInfo getGoods(@PathVariable Long id) {
+		return innerSearchService.getGoods(id);
+	}
 }

+ 97 - 2
search-console/src/main/java/com/uas/search/console/service/impl/SearchServiceImpl.java

@@ -8,6 +8,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import org.apache.lucene.document.Document;
@@ -43,6 +44,8 @@ import com.uas.search.console.util.SearchConstants;
 import com.uas.search.console.util.SearchUtils;
 import com.uas.search.exception.SearchException;
 import com.uas.search.grouping.DistinctGroupCollector;
+import com.uas.search.grouping.GoodsGroupCollector;
+import com.uas.search.model.CollectField;
 import com.uas.search.model.PageParams;
 import com.uas.search.model.PageParams.FilterField;
 import com.uas.search.service.SearchService;
@@ -882,14 +885,15 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 				// 筛选货源
 				if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_STORE_TYPE))) {
 					String storeType = filters.get(FilterField.GOODS_STORE_TYPE).toString();
-					booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.GOODS_ST_TYPE_FIELD, storeType),
+					booleanQuery.add(
+							new TermQuery(new Term(SearchConstants.GOODS_ST_TYPE_FIELD, storeType.toLowerCase())),
 							BooleanClause.Occur.FILTER);
 				}
 
 				// 筛选货币
 				if (!StringUtils.isEmpty(filters.get(FilterField.GOODS_CRNAME))) {
 					String crName = filters.get(FilterField.GOODS_CRNAME).toString();
-					booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.GOODS_CRNAME_FIELD, crName),
+					booleanQuery.add(new TermQuery(new Term(SearchConstants.GOODS_CRNAME_FIELD, crName.toLowerCase())),
 							BooleanClause.Occur.FILTER);
 				}
 
@@ -928,25 +932,33 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 			}
 			logger.info(booleanQuery.toString());
 
+			// 排序
 			Sort sort;
 			List<com.uas.search.model.Sort> sorts = pageParams.getSort();
 			if (sorts != null && !CollectionUtils.isEmpty(sorts)) {
 				SortField[] sortFields = new SortField[sorts.size()];
 				int i = 0;
 				for (com.uas.search.model.Sort s : sorts) {
+					if (s.getField() == null) {
+						throw new SearchException("排序字段不可为空:" + s);
+					}
 					switch (s.getField()) {
+					// 价格
 					case GO_RESERVE:
 						sortFields[i++] = new SortField(SearchConstants.GOODS_GO_RESERVE_FIELD, Type.DOUBLE,
 								s.isReverse());
 						break;
+					// 人民币价格
 					case GO_MINPRICERMB:
 						sortFields[i++] = new SortField(SearchConstants.GOODS_GO_MINPRICERMB_FIELD, Type.DOUBLE,
 								s.isReverse());
 						break;
+					// 美元价格
 					case GO_MINPRICEUSD:
 						sortFields[i++] = new SortField(SearchConstants.GOODS_GO_MINPRICEUSD_FIELD, Type.DOUBLE,
 								s.isReverse());
 						break;
+					// 打分
 					case GO_SEARCH:
 						sortFields[i++] = (SortField.FIELD_SCORE);
 						break;
@@ -996,6 +1008,89 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 		return map;
 	}
 
+	@Override
+	public List<Map<String, Object>> collectBySearchGoods(String keyword, CollectField collectedField,
+			Map<FilterField, Object> filters) {
+		if (collectedField == null && CollectionUtils.isEmpty(filters)) {
+			throw new SearchException("参数不合法:collectedField=" + collectedField + ", filter=" + filters);
+		}
+		IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.GOODS_TABLE_NAME);
+
+		List<Map<String, Object>> result = new ArrayList<>();
+		try {
+			BooleanQuery booleanQuery = new BooleanQuery();
+			if (!SearchUtils.isKeywordInvalid(keyword)) {
+				booleanQuery.add(setGoodsBoost(keyword), BooleanClause.Occur.MUST);
+			}
+			// 过滤
+			Set<Entry<FilterField, Object>> entrySet = filters.entrySet();
+			for (Entry<FilterField, Object> entry : entrySet) {
+				switch (entry.getKey()) {
+				case GOODS_KINDID:
+					booleanQuery.add(
+							new TermQuery(new Term(SearchConstants.GOODS_KI_ID_FIELD, entry.getValue().toString())),
+							BooleanClause.Occur.FILTER);
+					break;
+				case GOODS_BRANDID:
+					booleanQuery.add(
+							new TermQuery(new Term(SearchConstants.GOODS_BR_ID_FIELD, entry.getValue().toString())),
+							BooleanClause.Occur.FILTER);
+					break;
+				case GOODS_STORE_TYPE:
+					booleanQuery.add(new TermQuery(
+							new Term(SearchConstants.GOODS_ST_TYPE_FIELD, entry.getValue().toString().toLowerCase())),
+							BooleanClause.Occur.FILTER);
+					break;
+				case GOODS_CRNAME:
+					booleanQuery.add(new TermQuery(
+							new Term(SearchConstants.GOODS_CRNAME_FIELD, entry.getValue().toString().toLowerCase())),
+							BooleanClause.Occur.FILTER);
+					break;
+				default:
+					throw new SearchException("不支持该过滤字段:" + entry.getKey());
+				}
+			}
+			logger.info(booleanQuery.toString());
+
+			// 统计
+			String uniqueField;
+			Set<String> fieldsToLoad = new HashSet<>();
+			switch (collectedField) {
+			case GOODS_KIND:
+				uniqueField = SearchConstants.GOODS_KI_ID_FIELD;
+				fieldsToLoad.add(SearchConstants.GOODS_KI_ID_FIELD);
+				fieldsToLoad.add(SearchConstants.GOODS_KI_NAME_CN_FIELD);
+				break;
+			case GOODS_BRAND:
+				uniqueField = SearchConstants.GOODS_BR_ID_FIELD;
+				fieldsToLoad.add(SearchConstants.GOODS_BR_ID_FIELD);
+				fieldsToLoad.add(SearchConstants.GOODS_BR_UUID_FIELD);
+				fieldsToLoad.add(SearchConstants.GOODS_BR_NAME_CN_FIELD);
+				fieldsToLoad.add(SearchConstants.GOODS_BR_NAME_EN_FIELD);
+				break;
+			case GOODS_STORE_TYPE:
+				uniqueField = SearchConstants.GOODS_ST_TYPE_FIELD;
+				fieldsToLoad.add(SearchConstants.GOODS_ST_TYPE_FIELD);
+				break;
+			case GOODS_CRNAME:
+				uniqueField = SearchConstants.GOODS_CRNAME_FIELD;
+				fieldsToLoad.add(SearchConstants.GOODS_CRNAME_FIELD);
+				break;
+			default:
+				throw new SearchException("不支持该统计字段:" + collectedField);
+			}
+			GoodsGroupCollector collector = new GoodsGroupCollector(uniqueField, fieldsToLoad);
+			indexSearcher.search(booleanQuery, collector);
+			result = collector.getValues();
+		} catch (IOException e) {
+			logger.error("", e);
+		} finally {
+			SearchUtils.releaseIndexSearcher(indexSearcher);
+		}
+		return result;
+
+	}
+
 	@Override
 	public KindSimpleInfo getKind(Long id) {
 		return DocumentToObjectUtils.toKind(

+ 72 - 0
search-console/src/main/java/com/uas/search/grouping/GoodsGroupCollector.java

@@ -0,0 +1,72 @@
+package com.uas.search.grouping;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.LeafReader;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.search.SimpleCollector;
+
+/**
+ * 批次统计
+ * 
+ * @author sunyj
+ * @since 2017年7月12日 下午2:12:56
+ */
+public class GoodsGroupCollector extends SimpleCollector {
+
+	private Set<String> fieldsToLoad = new HashSet<>();
+
+	private Set<String> uniqueValues = new HashSet<>();
+
+	private String uniqueField;
+
+	private LeafReader reader;
+
+	private List<Map<String, Object>> values = new ArrayList<>();
+
+	public GoodsGroupCollector(String uniqueField, Set<String> fieldsToLoad) {
+		this.uniqueField = uniqueField;
+		this.fieldsToLoad.addAll(fieldsToLoad);
+	}
+
+	@Override
+	public boolean needsScores() {
+		return false;
+	}
+
+	@Override
+	protected void doSetNextReader(LeafReaderContext context) throws IOException {
+		super.doSetNextReader(context);
+		reader = context.reader();
+	}
+
+	@Override
+	public void collect(int doc) throws IOException {
+		if (null != reader) {
+			Map<String, Object> map = new HashMap<>();
+			Document document = reader.document(doc, fieldsToLoad);
+			String uniqueValue = document.get(uniqueField);
+			// 排除重复值
+			if (!uniqueValues.contains(uniqueValue)) {
+				uniqueValues.add(uniqueValue);
+				for (String field : fieldsToLoad) {
+					String value = document.get(field);
+					map.put(field, value);
+				}
+				values.add(map);
+			}
+		}
+	}
+
+	public List<Map<String, Object>> getValues() {
+		return values;
+	}
+
+}

+ 2 - 1
search-console/src/main/webapp/WEB-INF/views/console.html

@@ -24,12 +24,13 @@
 				</ol>
 
 
-				<strong><li class="title">统计类目、品牌</li></strong>
+				<strong><li class="title">统计</li></strong>
 				<ol>
 					<li><a target="_blank">search/kindsByComponent?keyword=aaa&brandId=56</a></li>
 					<li><a target="_blank">search/brandsByComponent?keyword=aaa&kindId=304</a></li>
 					<li><a target="_blank">search/kindIdsByComponent?keyword=aaa&brandId=56</a></li>
 					<li><a target="_blank">search/brandIdsByComponent?keyword=aaa&kindId=304</a></li>
+					<li><a target="_blank">search/collectBySearchGoods?keyword=23&collectedField=GOODS_KIND&filters={"GOODS_KINDID":401,"GOODS_BRANDID":45,"GOODS_STORE_TYPE":"DISTRIBUTION","GOODS_CRNAME":"RMB-USD"}</a></li>
 				</ol>
 
 				<strong><li class="title">联想词</li></strong>