Authored by wangnan

【图片搜索】 两次查询

@@ -2,6 +2,7 @@ package com.yoho.search.service.servicenew.impl; @@ -2,6 +2,7 @@ package com.yoho.search.service.servicenew.impl;
2 2
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
4 import com.yoho.error.event.SearchEvent; 4 import com.yoho.error.event.SearchEvent;
  5 +import com.yoho.search.base.utils.ConvertUtils;
5 import com.yoho.search.base.utils.EventReportEnum; 6 import com.yoho.search.base.utils.EventReportEnum;
6 import com.yoho.search.base.utils.ISearchConstants; 7 import com.yoho.search.base.utils.ISearchConstants;
7 import com.yoho.search.base.utils.ProductIndexEsField; 8 import com.yoho.search.base.utils.ProductIndexEsField;
@@ -54,6 +55,8 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl @@ -54,6 +55,8 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl
54 55
55 private static final String SCRIPT_NAME = "yoho_hamming_score"; 56 private static final String SCRIPT_NAME = "yoho_hamming_score";
56 57
  58 + private static final int VECTORS_32_QUERY_BACK_NUM = 100;
  59 +
57 private ApplicationEventPublisher publisher; 60 private ApplicationEventPublisher publisher;
58 61
59 @Autowired 62 @Autowired
@@ -85,13 +88,6 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl @@ -85,13 +88,6 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl
85 // 1.构造查询参数 88 // 1.构造查询参数
86 String vectors_32 = paramMap.get(VECTORS_32_KEY); 89 String vectors_32 = paramMap.get(VECTORS_32_KEY);
87 String vectors_128 = paramMap.get(VECTORS_128_KEY); 90 String vectors_128 = paramMap.get(VECTORS_128_KEY);
88 - //两个向量入参都不为空,默认用32位查询  
89 - String vectorsFieldName=VECTORS_32_KEY;  
90 - String vectorsValue=vectors_32;  
91 - if(StringUtils.isBlank(vectors_32)&&StringUtils.isNotBlank(vectors_128)){  
92 - vectorsFieldName=VECTORS_128_KEY;  
93 - vectorsValue=vectors_128;  
94 - }  
95 91
96 SearchParam searchParam = new SearchParam(); 92 SearchParam searchParam = new SearchParam();
97 int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum")); 93 int pageSize = StringUtils.isBlank(paramMap.get("viewNum")) ? 10 : Integer.parseInt(paramMap.get("viewNum"));
@@ -102,25 +98,41 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl @@ -102,25 +98,41 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl
102 if (pageSize > 50) { 98 if (pageSize > 50) {
103 pageSize = 50; 99 pageSize = 50;
104 } 100 }
  101 +
105 searchParam.setPage(page); 102 searchParam.setPage(page);
106 searchParam.setOffset((page - 1) * pageSize); 103 searchParam.setOffset((page - 1) * pageSize);
107 - searchParam.setSize(pageSize);  
108 - searchParam.setQuery(buildFunctionScoreQueryBuilder(vectorsFieldName,vectorsValue)); 104 + searchParam.setSize(VECTORS_32_QUERY_BACK_NUM);
  105 + searchParam.setQuery(buildFunctionScoreQueryBuilder(VECTORS_32_KEY, vectors_32, null));
109 106
110 //2.根据特征,查询SknImageVectors索引 107 //2.根据特征,查询SknImageVectors索引
  108 + //2.1第一次查询,用32维向量粗查询,召回一些skn
111 final String indexName = ISearchConstants.INDEX_NAME_IMAGE_VECTORS; 109 final String indexName = ISearchConstants.INDEX_NAME_IMAGE_VECTORS;
112 SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam); 110 SearchResult searchResult = searchCommonService.doSearch(indexName, searchParam);
113 SearchApiResult searchApiResult = new SearchApiResult(); 111 SearchApiResult searchApiResult = new SearchApiResult();
114 if (CollectionUtils.isNotEmpty(searchResult.getResultList())) { 112 if (CollectionUtils.isNotEmpty(searchResult.getResultList())) {
115 List<Map<String, Object>> sknList = getSknImageMap(searchResult.getResultList()); 113 List<Map<String, Object>> sknList = getSknImageMap(searchResult.getResultList());
  114 + String sknFilterString = "";
  115 + for (Map<String, Object> map : sknList) {
  116 + sknFilterString += map.get("productSkn").toString() + ",";
  117 + }
  118 + //2.2第二次查询,用128维向量粗查询这些skn
  119 + searchParam.setPage(page);
  120 + searchParam.setOffset((page - 1) * pageSize);
  121 + searchParam.setSize(pageSize);
  122 + //todo 先用32维的,后面要改成128的
  123 + searchParam.setQuery(buildFunctionScoreQueryBuilder(VECTORS_32_KEY, vectors_32, sknFilterString));
  124 + searchResult = searchCommonService.doSearch(indexName, searchParam);
  125 + if (CollectionUtils.isNotEmpty(searchResult.getResultList())) {
  126 + sknList = getSknImageMap(searchResult.getResultList());
116 List<String> querySknList = new ArrayList<>(); 127 List<String> querySknList = new ArrayList<>();
117 for (Map<String, Object> map : sknList) { 128 for (Map<String, Object> map : sknList) {
118 querySknList.add(map.get("productSkn").toString()); 129 querySknList.add(map.get("productSkn").toString());
119 } 130 }
120 //3.根据返回的skn列表,查询ProductIndex 131 //3.根据返回的skn列表,查询ProductIndex
121 searchApiResult = searchProductList(paramMap, querySknList, page, pageSize); 132 searchApiResult = searchProductList(paramMap, querySknList, page, pageSize);
122 - }  
123 logger.info("[func=searchSknByPhoto][cost={}]", System.currentTimeMillis() - begin); 133 logger.info("[func=searchSknByPhoto][cost={}]", System.currentTimeMillis() - begin);
  134 + }
  135 + }
124 return searchApiResult; 136 return searchApiResult;
125 } catch (Exception e) { 137 } catch (Exception e) {
126 publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SEARCHSKNBYPHOTO.getEventName(), EventReportEnum.SEARCHCONTROLLER_SEARCHSKNBYPHOTO.getFunctionName(), 138 publisher.publishEvent(new SearchEvent(EventReportEnum.SEARCHCONTROLLER_SEARCHSKNBYPHOTO.getEventName(), EventReportEnum.SEARCHCONTROLLER_SEARCHSKNBYPHOTO.getFunctionName(),
@@ -169,12 +181,10 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl @@ -169,12 +181,10 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl
169 return new SearchApiResult().setData(photoListData); 181 return new SearchApiResult().setData(photoListData);
170 } 182 }
171 183
172 - private FunctionScoreQueryBuilder buildFunctionScoreQueryBuilder(String vectorsFieldName,String vectorsValue) { 184 + private FunctionScoreQueryBuilder buildFunctionScoreQueryBuilder(String vectorsFieldName, String vectorsValue, String sknFilterString) {
173 MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery().boost(1.0f); 185 MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery().boost(1.0f);
174 //query 186 //query
175 FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(matchAllQueryBuilder); 187 FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(matchAllQueryBuilder);
176 - //filter  
177 - QueryBuilder filter = QueryBuilders.matchAllQuery().boost(1.0f);  
178 //script_score 188 //script_score
179 String[] feaArray = vectorsValue.split(","); 189 String[] feaArray = vectorsValue.split(",");
180 Long[] fea = new Long[feaArray.length]; 190 Long[] fea = new Long[feaArray.length];
@@ -190,7 +200,16 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl @@ -190,7 +200,16 @@ public class SknImageVectorsServiceImpl implements ISknImageVectorsService, Appl
190 Script script = new Script(inlineScript, ScriptService.ScriptType.INLINE, "native", params); 200 Script script = new Script(inlineScript, ScriptService.ScriptType.INLINE, "native", params);
191 ScriptScoreFunctionBuilder scriptBuilder = ScoreFunctionBuilders.scriptFunction(script); 201 ScriptScoreFunctionBuilder scriptBuilder = ScoreFunctionBuilders.scriptFunction(script);
192 //function_score 202 //function_score
  203 + //filter,sknFilterString为空是第一次粗查询,不为空是第二次精查询
  204 + if(StringUtils.isBlank(sknFilterString)){
  205 + QueryBuilder filter = QueryBuilders.matchAllQuery().boost(1.0f);
193 functionScoreQueryBuilder.add(filter, scriptBuilder); 206 functionScoreQueryBuilder.add(filter, scriptBuilder);
  207 + }else{
  208 + int[] sknArray = ConvertUtils.stringToIntArray(sknFilterString, ",");
  209 + BoolQueryBuilder boolFilter = QueryBuilders.boolQuery();
  210 + boolFilter.must(QueryBuilders.termsQuery("productSkn", sknArray));
  211 + functionScoreQueryBuilder.add(boolFilter, scriptBuilder);
  212 + }
194 functionScoreQueryBuilder.scoreMode("sum"); 213 functionScoreQueryBuilder.scoreMode("sum");
195 functionScoreQueryBuilder.boostMode(CombineFunction.REPLACE); 214 functionScoreQueryBuilder.boostMode(CombineFunction.REPLACE);
196 functionScoreQueryBuilder.maxBoost(3.4028235E38F); 215 functionScoreQueryBuilder.maxBoost(3.4028235E38F);