Prechádzať zdrojové kódy

支持根据"松下电阻"这样的品牌、类目组合关键词搜索器件

sunyj 9 rokov pred
rodič
commit
71f4f4aa20

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

@@ -54,7 +54,7 @@ public interface SearchService {
 	public List<Map<String, Object>> getBrands(String keyword) throws SearchException;
 
 	/**
-	 * 根据关键词搜索产品
+	 * 根据关键词搜索产品(关键词可能是器件、类目、品牌,甚至可能是类目、品牌的混合)
 	 * 
 	 * @param keyword
 	 * @param params

+ 81 - 18
search-console/src/main/java/com/uas/search/console/service/impl/SearchServiceImpl.java

@@ -58,11 +58,23 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 
 	@Override
 	public List<Long> getKindIds(String keyword) {
+		return getKindIds(keyword, Occur.MUST);
+	}
+
+	/**
+	 * 根据关键字搜索产品类目id
+	 * 
+	 * @param keyword
+	 *            关键词
+	 * @param occur
+	 * @return 符合条件的类目id
+	 */
+	private List<Long> getKindIds(String keyword, Occur occur) {
 		if (SearchUtils.isKeywordInvalid(keyword)) {
 			throw new SearchException("搜索关键词无效:" + keyword);
 		}
 		List<Long> ids = new ArrayList<Long>();
-		BooleanQuery booleanQuery = SearchUtils.getBooleanQuery(SearchConstants.KIND_NAMECN_FIELD, keyword);
+		BooleanQuery booleanQuery = SearchUtils.getBooleanQuery(SearchConstants.KIND_NAMECN_FIELD, keyword, occur);
 		logger.info(booleanQuery.toString());
 		List<Document> documents = SearchUtils.getDocuments(SearchConstants.KIND_TABLE_NAME, booleanQuery);
 		for (Document document : documents) {
@@ -91,14 +103,26 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 
 	@Override
 	public List<Long> getBrandIds(String keyword) {
+		return getBrandIds(keyword, Occur.MUST);
+	}
+
+	/**
+	 * 根据关键字搜索产品品牌id
+	 * 
+	 * @param keyword
+	 *            关键词
+	 * @param occur
+	 * @return 符合条件的品牌id
+	 */
+	private List<Long> getBrandIds(String keyword, Occur occur) {
 		if (SearchUtils.isKeywordInvalid(keyword)) {
 			throw new SearchException("搜索关键词无效:" + keyword);
 		}
 		List<Long> ids = new ArrayList<Long>();
 		BooleanQuery booleanQuery = new BooleanQuery();
-		booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.BRAND_NAMECN_FIELD, keyword),
+		booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.BRAND_NAMECN_FIELD, keyword, occur),
 				BooleanClause.Occur.SHOULD);
-		booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.BRAND_NAMEEN_FIELD, keyword),
+		booleanQuery.add(SearchUtils.getBooleanQuery(SearchConstants.BRAND_NAMEEN_FIELD, keyword, occur),
 				BooleanClause.Occur.SHOULD);
 		logger.info(booleanQuery.toString());
 		List<Document> documents = SearchUtils.getDocuments(SearchConstants.BRAND_TABLE_NAME, booleanQuery);
@@ -133,18 +157,40 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 	}
 
 	@Override
-	public Map<String, Object> getComponentIds(String keyword, PageParams page) {
+	public Map<String, Object> getComponentIds(String keyword, PageParams pageParams) {
+		Map<String, Object> searchComponentIds = getComponentIds(keyword, pageParams, null, null);
+		int total = (int) searchComponentIds.get("total");
+		if (total != 0) {
+			return searchComponentIds;
+		}
+		List<Long> kindIds = getKindIds(keyword, Occur.SHOULD);
+		List<Long> brandIds = getBrandIds(keyword, Occur.SHOULD);
+		return getComponentIds(null, pageParams, kindIds, brandIds);
+	}
+
+	/**
+	 * 根据关键词搜索产品
+	 * 
+	 * @param keyword
+	 * @param pageParams
+	 * @param kindIds
+	 * @param brandIds
+	 * @return
+	 * @throws SearchException
+	 */
+	private Map<String, Object> getComponentIds(String keyword, PageParams pageParams, List<Long> kindIds,
+			List<Long> brandIds) throws SearchException {
 		// 因为器件、属性值的数据量远比类目、品牌大得多,而且器件搜索可能还需进行分页,
-		// 所以涉及器件、属性值的搜索,都不能像类目和品牌一样直接利用SearchUtils.getDocuments方法
+		// 所以涉及器件、属性值的搜索,都不能像类目和品牌一样直接利用SearchUtils.getDocuments方法
 		IndexSearcher indexSearcher = SearchUtils.getIndexSearcher(SearchConstants.COMPONENT_TABLE_NAME);
 
-		if (page == null) {
-			page = new PageParams();
+		if (pageParams == null) {
+			pageParams = new PageParams();
 		}
-		if (page.getPage() == 0)
-			page.setPage(1);
-		if (page.getSize() == 0)
-			page.setSize(20);
+		if (pageParams.getPage() == 0)
+			pageParams.setPage(1);
+		if (pageParams.getSize() == 0)
+			pageParams.setSize(20);
 
 		Map<String, Object> map = new HashMap<String, Object>();
 		List<Long> ids = new ArrayList<Long>();
@@ -156,7 +202,7 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 				booleanQuery.add(prefixQuery, BooleanClause.Occur.MUST);
 			}
 
-			Map<String, Object> filters = page.getFilters();
+			Map<String, Object> filters = pageParams.getFilters();
 			if (!CollectionUtils.isEmpty(filters)) {
 				// 筛选类目
 				if (!StringUtils.isEmpty(filters.get(com.uas.search.utils.SearchConstants.COMPONENT_KINDID_KEY))) {
@@ -225,15 +271,32 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 					}
 				}
 			}
+			if (!CollectionUtils.isEmpty(kindIds)) {
+				BooleanQuery booleanQuery2 = new BooleanQuery();
+				for (Long id : kindIds) {
+					booleanQuery2.add(new TermQuery(new Term(SearchConstants.COMPONENT_KINDID_FIELD, id.toString())),
+							Occur.SHOULD);
+				}
+				booleanQuery.add(booleanQuery2, Occur.MUST);
+			}
+			if (!CollectionUtils.isEmpty(brandIds)) {
+				BooleanQuery booleanQuery2 = new BooleanQuery();
+				for (Long id : brandIds) {
+					booleanQuery2.add(new TermQuery(new Term(SearchConstants.COMPONENT_BRANDID_FIELD, id.toString())),
+							Occur.SHOULD);
+				}
+				booleanQuery.add(booleanQuery2, Occur.MUST);
+			}
 			logger.info(booleanQuery.toString());
 			TopDocs hits;
-			if (page.getPage() > 1) {// 不是第一页
-				TopDocs previousHits = indexSearcher.search(booleanQuery, (page.getPage() - 1) * page.getSize());
+			if (pageParams.getPage() > 1) {// 不是第一页
+				TopDocs previousHits = indexSearcher.search(booleanQuery,
+						(pageParams.getPage() - 1) * pageParams.getSize());
 				ScoreDoc[] previousScoreDocs = previousHits.scoreDocs;
 				ScoreDoc after = previousScoreDocs[previousScoreDocs.length - 1];
-				hits = indexSearcher.searchAfter(after, booleanQuery, page.getSize());
+				hits = indexSearcher.searchAfter(after, booleanQuery, pageParams.getSize());
 			} else {
-				hits = indexSearcher.search(booleanQuery, page.getSize());
+				hits = indexSearcher.search(booleanQuery, pageParams.getSize());
 			}
 
 			ScoreDoc[] scoreDocs = hits.scoreDocs;
@@ -246,8 +309,8 @@ public class SearchServiceImpl implements SearchService, InnerSearchService {
 				ids.add(Long.parseLong(componentId));
 			}
 			map.put("componentIds", ids);
-			map.put("page", page.getPage());
-			map.put("size", page.getSize());
+			map.put("page", pageParams.getPage());
+			map.put("size", pageParams.getSize());
 			map.put("total", hits.totalHits);
 		} catch (IOException e) {
 			e.printStackTrace();

+ 17 - 2
search-console/src/main/java/com/uas/search/console/util/SearchUtils.java

@@ -9,7 +9,7 @@ import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.PrefixQuery;
@@ -74,6 +74,21 @@ public class SearchUtils {
 	 * @return
 	 */
 	public static BooleanQuery getBooleanQuery(String field, String keyword) {
+		return getBooleanQuery(field, keyword, Occur.MUST);
+	}
+
+	/**
+	 * 对搜索词进行分词后组合得到BooleanQuery
+	 * 
+	 * @param field
+	 *            搜索的域名
+	 * @param keyword
+	 *            搜索关键词
+	 * @param occur
+	 *            多个Query之间的关系
+	 * @return
+	 */
+	public static BooleanQuery getBooleanQuery(String field, String keyword, Occur occur) {
 		if (StringUtils.isEmpty(field) || StringUtils.isEmpty(keyword)) {
 			return null;
 		}
@@ -84,7 +99,7 @@ public class SearchUtils {
 			tokenStream.reset();
 			CharTermAttribute cta = tokenStream.addAttribute(CharTermAttribute.class);
 			while (tokenStream.incrementToken()) {
-				booleanQuery.add(new PrefixQuery(new Term(field, cta.toString())), BooleanClause.Occur.MUST);
+				booleanQuery.add(new PrefixQuery(new Term(field, cta.toString())), occur);
 			}
 			tokenStream.close();
 			analyzer.close();