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

collect kind and brand directly from component to avoid TooManyClauses

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

+ 1 - 0
src/main/java/com/uas/search/constant/SearchConstants.java

@@ -100,6 +100,7 @@ public class SearchConstants {
 	public static final String COMPONENT_BR_ID_FIELD = "br_id";
 	public static final String COMPONENT_BR_NAMECN_FIELD = "br_name_cn";
 	public static final String COMPONENT_BR_NAMEEN_FIELD = "br_name_en";
+	public static final String COMPONENT_BR_UUID_FIELD = "br_uuid";
     public static final String COMPONENT_BR_VISIT_COUNT_FIELD = "br_visit_count";
     public static final String COMPONENT_BR_SEARCH_COUNT_FIELD = "br_search_count";
     public static final String COMPONENT_BR_WEIGHT_FIELD = "br_weight";

+ 2 - 2
src/main/java/com/uas/search/controller/SearchController.java

@@ -151,7 +151,7 @@ public class SearchController {
 
 	@RequestMapping("/kindsByComponent")
 	@ResponseBody
-	public List<Map<String, Object>> searchKindsBySearchComponent(String keyword, String brandId,
+	public Set<Map<String, Object>> searchKindsBySearchComponent(String keyword, String brandId,
 																  HttpServletRequest request) {
 		return searchService.getKindsBySearchComponent(keyword, brandId);
 	}
@@ -164,7 +164,7 @@ public class SearchController {
 
 	@RequestMapping("/brandsByComponent")
 	@ResponseBody
-	public List<Map<String, Object>> searchBrandsBySearchComponent(String keyword, String kindId,
+	public Set<Map<String, Object>> searchBrandsBySearchComponent(String keyword, String kindId,
 																   HttpServletRequest request) {
 		return searchService.getBrandsBySearchComponent(keyword, kindId);
 	}

+ 60 - 11
src/main/java/com/uas/search/grouping/DistinctGroupCollector.java

@@ -1,27 +1,40 @@
 package com.uas.search.grouping;
 
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-
+import com.uas.search.util.ArrayUtils;
+import org.apache.lucene.document.Document;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.search.SimpleCollector;
 
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
 public class DistinctGroupCollector extends SimpleCollector {
 
 	private final String groupField;
 
-	private final Set<String> fieldsToLoad;
+	private final CollectField[] collectFields;
+
+	private final Set<String> fieldsToLoad = new HashSet<>();
 
 	private LeafReader reader;
 
-	private Set<Long> values = new HashSet<Long>();
+	private Set<Long> values = new HashSet<>();
 
-	public DistinctGroupCollector(String groupField) {
+	private Set<Map<String, Object>> collectValues = new HashSet<>();
+
+	public DistinctGroupCollector(String groupField, CollectField... collectFields) {
 		this.groupField = groupField;
-		this.fieldsToLoad = new HashSet<String>();
+		this.collectFields = collectFields;
 		this.fieldsToLoad.add(groupField);
+		if(collectFields!=null){
+			for(CollectField collectField : collectFields){
+				fieldsToLoad.add(collectField.getFieldName());
+			}
+		}
 	}
 
 	@Override
@@ -37,10 +50,22 @@ public class DistinctGroupCollector extends SimpleCollector {
 
 	@Override
 	public void collect(int doc) throws IOException {
-		if (null != reader) {
-			String value = reader.document(doc, fieldsToLoad).get(groupField);
-			if (null != value) {
+		if (reader != null) {
+			Document document = reader.document(doc, fieldsToLoad);
+			String value = document.get(groupField);
+			if (value != null) {
 				values.add(Long.parseLong(value));
+				// 统计指定信息
+				if(!ArrayUtils.isEmpty(collectFields)){
+					Map<String, Object> collectValue = new HashMap<>();
+					for(CollectField collectField : collectFields){
+						String v = document.get(collectField.getFieldName());
+						if(v != null){
+							collectValue.put(collectField.getDisplayName(), v);
+						}
+					}
+					collectValues.add(collectValue);
+				}
 			}
 		}
 	}
@@ -49,4 +74,28 @@ public class DistinctGroupCollector extends SimpleCollector {
 		return values;
 	}
 
+	public Set<Map<String, Object>> getCollectValues(){
+		return collectValues;
+	}
+
+	/**
+	 * 用于统计的字段
+	 */
+	public static class CollectField {
+		private String fieldName;
+		private String displayName;
+
+		public CollectField(String fieldName, String displayName) {
+			this.fieldName = fieldName;
+			this.displayName = displayName;
+		}
+
+		public String getFieldName() {
+			return fieldName;
+		}
+
+		public String getDisplayName() {
+			return displayName;
+		}
+	}
 }

+ 2 - 2
src/main/java/com/uas/search/service/SearchService.java

@@ -153,7 +153,7 @@ public interface SearchService {
 	 * @return
 	 * @throws SearchException
 	 */
-	public List<Map<String, Object>> getKindsBySearchComponent(String keyword, String brandId) throws SearchException;
+	public Set<Map<String, Object>> getKindsBySearchComponent(String keyword, String brandId) throws SearchException;
 
 	/**
 	 * 根据产品搜索获取产品品牌id的统计
@@ -175,7 +175,7 @@ public interface SearchService {
 	 * @return
 	 * @throws SearchException
 	 */
-	public List<Map<String, Object>> getBrandsBySearchComponent(String keyword, String kindId) throws SearchException;
+	public Set<Map<String, Object>> getBrandsBySearchComponent(String keyword, String kindId) throws SearchException;
 
 	/**
 	 * 根据输入获取联想词(包括器件、类目、品牌,按顺序获取,数量不足,才会获取下一个)

+ 49 - 82
src/main/java/com/uas/search/service/impl/SearchServiceImpl.java

@@ -383,116 +383,83 @@ public class SearchServiceImpl implements SearchService {
 
 	@Override
 	public Set<Long> getKindIdsBySearchComponent(String keyword, String brandId) {
-		if (SearchUtils.isKeywordInvalid(keyword)) {
-			throw new SearchException("搜索关键词无效:" + keyword);
+		Query filter = null;
+		// 筛选品牌
+		if (!StringUtils.isEmpty(brandId)) {
+			filter = new TermQuery(new Term(SearchConstants.COMPONENT_BR_ID_FIELD, brandId));
 		}
-		IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.COMPONENT_TABLE_NAME);
-
-		Set<Long> kindIds = new HashSet<Long>();
-		try {
-			BooleanQuery booleanQuery = new BooleanQuery();
-
-			keyword = URLDecoder.decode(keyword, "UTF-8");
-			booleanQuery.add(setBoost(keyword), BooleanClause.Occur.MUST);
-
-			// 筛选品牌
-			if (!StringUtils.isEmpty(brandId)) {
-				TermQuery brandQuery = new TermQuery(new Term(SearchConstants.COMPONENT_BR_ID_FIELD, brandId));
-				booleanQuery.add(brandQuery, BooleanClause.Occur.MUST);
-			}
-			logger.info(booleanQuery.toString());
+		return collectBySearchComponent(keyword, filter, SearchConstants.COMPONENT_KI_ID_FIELD).getValues();
+	}
 
-			DistinctGroupCollector collector = new DistinctGroupCollector(SearchConstants.COMPONENT_KI_ID_FIELD);
-			indexSearcher.search(booleanQuery, collector);
-			kindIds = collector.getValues();
-		} catch (IOException e) {
-			logger.error("", e);
-		} finally {
-			SearchUtils.releaseIndexSearcher(indexSearcher);
+	@Override
+	public Set<Map<String, Object>> getKindsBySearchComponent(String keyword, String brandId) {
+		Query filter = null;
+		// 筛选品牌
+		if (!StringUtils.isEmpty(brandId)) {
+			filter = new TermQuery(new Term(SearchConstants.COMPONENT_BR_ID_FIELD, brandId));
 		}
-
-		return kindIds;
+		return collectBySearchComponent(keyword, filter, SearchConstants.KIND_ID_FIELD,
+				new DistinctGroupCollector.CollectField(SearchConstants.KIND_ID_FIELD, "id"),
+				new DistinctGroupCollector.CollectField(SearchConstants.KIND_NAMECN_FIELD, "nameCn"))
+				.getCollectValues();
 	}
 
 	@Override
-	public List<Map<String, Object>> getKindsBySearchComponent(String keyword, String brandId) {
-		Set<Long> kindIds = getKindIdsBySearchComponent(keyword, brandId);
-		List<Map<String, Object>> kinds = new ArrayList<Map<String, Object>>();
-		if (CollectionUtils.isEmpty(kindIds)) {
-			return kinds;
+	public Set<Long> getBrandIdsBySearchComponent(String keyword, String kindId) {
+		Query filter = null;
+		// 筛选类目
+		if (!StringUtils.isEmpty(kindId)) {
+			filter = new TermQuery(new Term(SearchConstants.COMPONENT_KI_ID_FIELD, kindId));
 		}
+		return collectBySearchComponent(keyword, filter, SearchConstants.COMPONENT_BR_ID_FIELD).getValues();
+	}
 
-		BooleanQuery booleanQuery = new BooleanQuery();
-		for (Long kindId : kindIds) {
-			booleanQuery.add(new TermQuery(new Term(SearchConstants.KIND_ID_FIELD, String.valueOf(kindId))),
-					BooleanClause.Occur.SHOULD);
-		}
-		List<Document> documents = SearchUtils.getDocuments(SearchConstants.KIND_TABLE_NAME, booleanQuery).getContent();
-		for (Document document : documents) {
-			Map<String, Object> kind = new HashMap<String, Object>();
-			kind.put("id", Long.parseLong(document.get(SearchConstants.KIND_ID_FIELD)));
-			kind.put("nameCn", document.get(SearchConstants.KIND_NAMECN_FIELD));
-			kinds.add(kind);
+	@Override
+	public Set<Map<String, Object>> getBrandsBySearchComponent(String keyword, String kindId) {
+		Query filter = null;
+		// 筛选类目
+		if (!StringUtils.isEmpty(kindId)) {
+			filter = new TermQuery(new Term(SearchConstants.COMPONENT_KI_ID_FIELD, kindId));
 		}
-		return kinds;
+		return collectBySearchComponent(keyword, filter, SearchConstants.COMPONENT_BR_ID_FIELD,
+				new DistinctGroupCollector.CollectField(SearchConstants.COMPONENT_BR_ID_FIELD, "id"),
+				new DistinctGroupCollector.CollectField(SearchConstants.COMPONENT_BR_UUID_FIELD, "uuid"),
+				new DistinctGroupCollector.CollectField(SearchConstants.COMPONENT_BR_NAMECN_FIELD, "nameCn"))
+				.getCollectValues();
 	}
 
-	@Override
-	public Set<Long> getBrandIdsBySearchComponent(String keyword, String kindId) {
+    /**
+     * 搜索器件时统计指定信息
+     *
+     * @param keyword       关键词
+     * @param filter        过滤条件
+     * @param groupField    统计的单个字段(多为 id)
+     * @param collectFields 统计的多个字段(详细信息),可为空
+     * @return 统计信息
+     */
+    private DistinctGroupCollector collectBySearchComponent(String keyword, Query filter, String groupField, DistinctGroupCollector.CollectField... collectFields){
 		if (SearchUtils.isKeywordInvalid(keyword)) {
 			throw new SearchException("搜索关键词无效:" + keyword);
 		}
 		IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.COMPONENT_TABLE_NAME);
-
-		Set<Long> brandIds = new HashSet<Long>();
 		try {
 			BooleanQuery booleanQuery = new BooleanQuery();
-
 			keyword = URLDecoder.decode(keyword, "UTF-8");
 			booleanQuery.add(setBoost(keyword), BooleanClause.Occur.MUST);
 
-			// 筛选类目
-			if (!StringUtils.isEmpty(kindId)) {
-				TermQuery kindQuery = new TermQuery(new Term(SearchConstants.COMPONENT_KI_ID_FIELD, kindId));
-				booleanQuery.add(kindQuery, BooleanClause.Occur.MUST);
+			if(filter != null){
+				booleanQuery.add(filter, Occur.FILTER);
 			}
 			logger.info(booleanQuery.toString());
 
-			DistinctGroupCollector collector = new DistinctGroupCollector(SearchConstants.COMPONENT_BR_ID_FIELD);
+			DistinctGroupCollector collector = new DistinctGroupCollector(groupField, collectFields);
 			indexSearcher.search(booleanQuery, collector);
-			brandIds = collector.getValues();
+			return collector;
 		} catch (IOException e) {
-			logger.error("", e);
+			throw new IllegalStateException("统计失败", e);
 		} finally {
 			SearchUtils.releaseIndexSearcher(indexSearcher);
 		}
-
-		return brandIds;
-	}
-
-	@Override
-	public List<Map<String, Object>> getBrandsBySearchComponent(String keyword, String kindId) {
-		Set<Long> brandIds = getBrandIdsBySearchComponent(keyword, kindId);
-		List<Map<String, Object>> brands = new ArrayList<Map<String, Object>>();
-		if (CollectionUtils.isEmpty(brandIds)) {
-			return brands;
-		}
-
-		BooleanQuery booleanQuery = new BooleanQuery();
-		for (Long brandId : brandIds) {
-			booleanQuery.add(new TermQuery(new Term(SearchConstants.BRAND_ID_FIELD, String.valueOf(brandId))),
-					BooleanClause.Occur.SHOULD);
-		}
-		List<Document> documents = SearchUtils.getDocuments(SearchConstants.BRAND_TABLE_NAME, booleanQuery)
-				.getContent();
-		for (Document document : documents) {
-			Map<String, Object> brand = new HashMap<String, Object>();
-			brand.put("id", Long.parseLong(document.get(SearchConstants.BRAND_ID_FIELD)));
-			brand.put("uuid", document.get(SearchConstants.BRAND_UUID_FIELD));
-			brand.put("nameCn", document.get(SearchConstants.BRAND_NAMECN_FIELD));
-			brands.add(brand);
-		}
-		return brands;
 	}
 
 	@Override

+ 1 - 0
src/main/java/com/uas/search/util/DocumentToObjectUtils.java

@@ -136,6 +136,7 @@ public class DocumentToObjectUtils {
         if (!StringUtils.isEmpty(document.get(SearchConstants.COMPONENT_BR_NAMEEN_FIELD))) {
             brand.setNameEn(document.get(SearchConstants.COMPONENT_BR_NAMEEN_FIELD));
         }
+		brand.setUuid(document.get(SearchConstants.COMPONENT_BR_UUID_FIELD));
         if (!StringUtils.isEmpty(document.get(SearchConstants.COMPONENT_BR_VISIT_COUNT_FIELD))) {
             brand.setVisitCount(Long.valueOf(document.get(SearchConstants.COMPONENT_BR_VISIT_COUNT_FIELD)));
         }

+ 3 - 1
src/main/java/com/uas/search/util/ObjectToDocumentUtils.java

@@ -134,7 +134,8 @@ public class ObjectToDocumentUtils {
 				|| StringUtils.isEmpty(component.getCode()) || component.getKind() == null
                 || component.getKind().getId() == null || StringUtils.isEmpty(component.getKind().getNameCn())
                 || component.getKind().getLevel() == null || component.getBrand() == null
-                || component.getBrand().getId() == null || StringUtils.isEmpty(component.getBrand().getNameCn())) {
+                || component.getBrand().getId() == null || StringUtils.isEmpty(component.getBrand().getNameCn())
+				|| StringUtils.isEmpty(component.getBrand().getUuid())) {
 			return null;
 		}
 		Document document = new Document();
@@ -171,6 +172,7 @@ public class ObjectToDocumentUtils {
 		if(brand.getNameEn() != null){
 			document.add(new TextField(SearchConstants.COMPONENT_BR_NAMEEN_FIELD, brand.getNameEn(), Store.YES));
 		}
+		document.add(new StringField(SearchConstants.COMPONENT_BR_UUID_FIELD, brand.getUuid(), Store.YES));
         if (brand.getVisitCount() != null) {
             document.add(new DoubleDocValuesField(SearchConstants.COMPONENT_BR_VISIT_COUNT_FIELD, brand.getVisitCount()));
             document.add(new LongField(SearchConstants.COMPONENT_BR_VISIT_COUNT_FIELD, brand.getVisitCount(), Store.YES));