ElasticSearch6.0 高级应用之 多字段聚合Aggregation(二)
ElasticSearch6.0 多字段聚合网上完整的资料很少 ,所以作者经过查阅资料,编写了聚合高级使用例子
例子是根据电商搜索实际场景模拟出来的
希望给大家带来帮助!
下面我们开始吧!
1. 创建索引的映射关系
1 PUT gome_market 2 { 3 "mappings": { 4 "goods": { 5 "dynamic_templates": [ 6 { 7 "dynamicFields": { 8 "match_mapping_type": "string", 9 "path_match":"dynamicFields.*_sku_attr", 10 "mapping":{ 11 "type": "keyword" 12 } 13 } 14 } 15 ], 16 "properties":{ 17 "id":{ 18 "type": "keyword" 19 }, 20 "category_first_id":{ 21 "type": "keyword" 22 }, 23 "category_first":{ 24 "type": "keyword" 25 }, 26 "category_second_id":{ 27 "type": "keyword" 28 }, 29 "category_second":{ 30 "type": "keyword" 31 }, 32 "category_third_id":{ 33 "type": "keyword" 34 }, 35 "category_third":{ 36 "type": "keyword" 37 }, 38 "brand_id":{ 39 "type": "keyword" 40 }, 41 "brand":{ 42 "type": "text", 43 "analyzer":"ik_max_word", 44 "search_analyzer":"ik_max_word", 45 "copy_to":"full_name" 46 }, 47 "shop":{ 48 "type": "keyword" 49 }, 50 "attr_name":{ 51 "type": "keyword", 52 "index":"true" 53 54 }, 55 "sku":{ 56 "type": "keyword", 57 "index":"true" 58 }, 59 "spu":{ 60 "type": "keyword", 61 "index":"true" 62 }, 63 "gome_sku":{ 64 "type": "keyword" 65 }, 66 "product_ch":{ 67 "type": "text", 68 "analyzer":"ik_max_word", 69 "search_analyzer":"ik_max_word", 70 "copy_to":"full_name" 71 }, 72 "adver":{ 73 "type": "keyword" 74 }, 75 "product_img":{ 76 "type": "keyword" 77 }, 78 "product_proto_price":{ 79 "type": "double" 80 }, 81 "product_sale_price":{ 82 "type": "double" 83 }, 84 "is_sku":{ 85 "type": "boolean" 86 }, 87 "is_self":{ 88 "type": "boolean" 89 }, 90 "shop_flag":{ 91 "type": "long" 92 }, 93 "is_in_store":{ 94 "type": "boolean" 95 }, 96 "is_shelves":{ 97 "type": "boolean" 98 }, 99 "is_suit":{ 100 "type": "boolean" 101 }, 102 "good_comment_rate":{ 103 "type": "long" 104 }, 105 "sale_num":{ 106 "type": "long" 107 }, 108 "spu_score":{ 109 "type": "long" 110 }, 111 "dynamic_attrs":{ 112 "type": "keyword" 113 }, 114 "full_name":{ 115 "type": "text", 116 "store":"true" 117 }, 118 "create_time":{ 119 "type":"date" 120 } 121 } 122 } 123 } 124 }
2.创建索引数据
请参照上一篇文章
3.Controller层 创建 SuperMarketSearchController
1 package com.elastic.controller; 2 3 import com.alibaba.fastjson.JSONObject; 4 5 import com.elastic.service.inter.SuperMarketSearchService; 6 import com.elastic.service.pojo.SearchBean; 7 import org.apache.commons.lang.StringUtils; 8 import org.apache.log4j.Logger; 9 import org.springframework.stereotype.Controller; 10 import org.springframework.web.bind.annotation.RequestMapping; 11 12 import javax.annotation.Resource; 13 import javax.servlet.http.HttpServletRequest; 14 import javax.servlet.http.HttpServletResponse; 15 import java.io.*; 16 import java.net.URLDecoder; 17 import java.nio.charset.Charset; 18 19 @Controller 20 public class SuperMarketSearchController extends BaseController { 21 22 private static final Logger logger = Logger.getLogger(SuperMarketSearchController.class); 23 24 @Resource(name = "superMarketSearchServiceImpl") 25 private SuperMarketSearchService searchService; 26 27 @RequestMapping(value = "/s.action") 28 public String searchForPost(HttpServletRequest request, HttpServletResponse response) throws IOException { 29 try { 30 String param = getParam(request); 31 logger.info("请求参数:" + param); 32 SearchBean bean = JSONObject.toJavaObject(JSONObject.parseObject(param), SearchBean.class); 33 bean.setQuery(bean.getQuery() != null ? URLDecoder.decode(bean.getQuery(), "UTF-8") : null); 34 String re = searchService.searchByBean(bean); 35 printReturnVal(response, re); 36 } catch (Exception e) { 37 e.printStackTrace(); 38 logger.error(e.getMessage()); 39 printReturnVal(response, assemReturn("[]", 500, "系统异常,请检查参数:" + e.getMessage())); 40 } 41 return null; 42 } 43 44 45 46 @RequestMapping(value = "/suggest") 47 public void suggest(HttpServletRequest request, HttpServletResponse response) throws Exception { 48 String keyword = request.getParameter("keyword"); 49 // String newKeyWord=""; 50 // if (!StringUtils.isEmpty(keyword)){ 51 // newKeyWord = new String(keyword.getBytes("ISO-8859-1"), "UTF-8"); 52 // } 53 SearchBean bean = new SearchBean(); 54 // bean.setQuery(newKeyWord==""?"********":newKeyWord); 55 bean.setQuery(keyword); 56 PrintWriter out = null; 57 String suggests = searchService.suggestByBean(bean); 58 printReturnVal(response, suggests); 59 } 60 61 private void printReturnVal(HttpServletResponse response, String returnVal) { 62 PrintWriter out = null; 63 try { 64 response.setCharacterEncoding("UTF-8"); 65 response.setContentType("application/json"); 66 out = response.getWriter(); 67 System.out.println(returnVal); 68 out.print(returnVal); 69 out.flush(); 70 } catch (IOException e) { 71 e.printStackTrace(); 72 } 73 } 74 75 private String getParam(HttpServletRequest request) throws IOException { 76 StringBuffer sb = new StringBuffer(); 77 InputStream is = request.getInputStream(); 78 InputStreamReader isr = new InputStreamReader(is, Charset.forName("UTF-8")); 79 BufferedReader br = new BufferedReader(isr); 80 String s = ""; 81 while ((s = br.readLine()) != null) { 82 sb.append(s); 83 } 84 isr.close(); 85 br.close(); 86 String str = sb.toString(); 87 logger.info("requstParam=" + str); 88 String param = ""; 89 JSONObject jsonObject = JSONObject.parseObject(str); 90 if (jsonObject.getString("body") != null && !jsonObject.getString("body").isEmpty()) { 91 param = jsonObject.getString("body"); 92 } else { 93 param = str; 94 } 95 return param; 96 } 97 98 }
4. Service层 interface SuperMarketSearchService
1 package com.elastic.service.inter; 2 3 4 import com.elastic.service.pojo.SearchBean; 5 6 public interface SuperMarketSearchService { 7 8 public String searchByBean(SearchBean bean); 9 10 public String suggestByBean(SearchBean bean); 11 12 }
Service层 Impl 实现 SuperMarketSearchServiceImpl
1 package com.elastic.service.impl; 2 3 import com.elastic.common.conn.EsClient; 4 import com.elastic.service.inter.SuperMarketSearchService; 5 import com.elastic.service.pojo.Filter; 6 import com.elastic.service.pojo.SearchBean; 7 import com.elastic.service.vo.SearchParams; 8 import com.elastic.service.vo.SearchReturn; 9 import com.elastic.util.SpringApplicationUtils; 10 import org.apache.commons.lang.StringUtils; 11 import org.elasticsearch.action.search.SearchRequestBuilder; 12 import org.elasticsearch.action.search.SearchResponse; 13 import org.elasticsearch.client.transport.TransportClient; 14 import org.elasticsearch.index.query.BoolQueryBuilder; 15 import org.elasticsearch.index.query.Operator; 16 import org.elasticsearch.index.query.QueryBuilder; 17 import org.elasticsearch.index.query.QueryBuilders; 18 import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; 19 import org.elasticsearch.index.query.functionscore.ScriptScoreFunctionBuilder; 20 import org.elasticsearch.script.Script; 21 import org.elasticsearch.script.ScriptType; 22 import org.elasticsearch.search.aggregations.*; 23 import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter; 24 import org.elasticsearch.search.aggregations.bucket.range.Range; 25 import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder; 26 import org.elasticsearch.search.aggregations.bucket.terms.*; 27 import org.springframework.stereotype.Service; 28 29 import java.math.BigDecimal; 30 import java.util.*; 31 import java.util.function.BiConsumer; 32 33 import static org.elasticsearch.index.query.QueryBuilders.functionScoreQuery; 34 35 /** 36 * Created by xiaotian on 2017/12/23. 37 */ 38 @Service 39 public class SuperMarketSearchServiceImpl implements SuperMarketSearchService { 40 41 private EsClient esClient; 42 43 @Override 44 public String searchByBean(SearchBean bean) { 45 try { 46 esClient = SpringApplicationUtils.getBean(EsClient.class); 47 SearchRequestBuilder searchRequestBuilder = esClient.getConnection().prepareSearch("gome_market").setTypes("goods"); 48 long s = System.currentTimeMillis(); 49 50 bean.setIsFacet(bean.getIsFacet() == null ? true : bean.getIsFacet()); 51 if (bean.getIsFacet()){ 52 //聚合 53 String[] attrFacet = new String[]{"attr_name"}; 54 bean.setFacetFields(attrFacet); 55 56 } 57 SearchResponse searchResponse = assemQueryByBean(searchRequestBuilder, esClient, bean); 58 59 bean.setFacetFields(null); 60 if (bean.getIsFacet()){ 61 String[] docAttrFields = getDocAttrFields(searchResponse); 62 bean.setFacetFields(docAttrFields); 63 SearchRequestBuilder requestBuilder = esClient.getConnection().prepareSearch("gome_market").setTypes("goods"); 64 SearchResponse response = assemQueryByBean(requestBuilder, esClient, bean); 65 66 Aggregations aggregations = response.getAggregations(); 67 Map<String, Aggregation> asMap = aggregations.getAsMap(); 68 List<String> list = new ArrayList<>(); 69 for (String key: bean.getFacetFields()) { 70 InternalFilter filter = aggregations.get(key); 71 Map<String, Aggregation> aggMap = filter.getAggregations().getAsMap(); 72 Iterator<String> iterator = filter.getAggregations().getAsMap().keySet().iterator(); 73 while (iterator.hasNext()){ 74 String keys = iterator.next(); 75 if ("range".equals(keys)){ 76 continue; 77 } 78 if (aggMap.get(keys)==null|| aggMap.get(keys) instanceof UnmappedTerms){ 79 continue; 80 } 81 StringTerms aggregation = (StringTerms)aggMap.get(keys); 82 aggregation.getBuckets().forEach(bucket -> { 83 System.out.println(keys+"-->"+bucket.getKey()+":"+bucket.getDocCount()); 84 list.add(keys+"-->"+bucket.getKey()+":"+bucket.getDocCount()); 85 }); 86 87 } 88 } 89 System.out.println("list="+list); 9 97 Range range = response.getAggregations().get("range"); 98 99 range.getBuckets().forEach(bucket ->{ 100 102 System.out.println(String.format("key [%s], from [%s], to [%s], doc_count [%d]", bucket.getKey(), bucket.getFrom(),bucket.getTo(),bucket.getDocCount())); 103 104 }); 105 }else { 106 107 } 108 109 110 } catch (Exception e) { 111 e.printStackTrace(); 112 } finally { 113 } 114 115 return null; 116 } 117 118 private String[] getDocAttrFields(SearchResponse searchResponse) { 119 List<String> attrFieldList = new ArrayList<>(); 120 attrFieldList.add("category_third"); 121 attrFieldList.add("category_third_id"); 122 if (searchResponse.getAggregations().get("attr_name")!=null){ 123 InternalFilter aggFilter= searchResponse.getAggregations().get("attr_name"); 124 Map<String, Aggregation> aggMap = aggFilter.getAggregations().getAsMap(); 125 Iterator<String> iterator = aggFilter.getAggregations().getAsMap().keySet().iterator(); 126 while (iterator.hasNext()){ 127 String keys = iterator.next(); 128 StringTerms aggregation = (StringTerms)aggMap.get(keys); 129 aggregation.getBuckets().forEach(bucket -> { 130 attrFieldList.add("dynamicFields."+bucket.getKey()+""); 131 System.out.println(keys+"-->"+bucket.getKey()+":"+bucket.getDocCount()); 132 }); 133 134 } 135 } 136 137 return attrFieldList.toArray(new String[attrFieldList.size()]); 138 } 139 140 @Override 141 public String suggestByBean(SearchBean bean) { 142 return null; 143 } 144 145 146 private SearchResponse assemQueryByBean(SearchRequestBuilder searchRequest, EsClient esClient, SearchBean bean) throws Exception { 147 148 Map<String, Object> params = new HashMap<>(); 149 params.put("num1", 1); 150 params.put("num2", 2); 151 152 //String inlineScript = "long age;if (doc['age'].value < 45) age = doc['age'].value + 50; return age * params.num1;"; 153 String inlineScript = " return doc['age'].value * params.num1;"; 154 // + "return (diff +num1+num2)"; 155 Script script = new Script(ScriptType.INLINE,"painless",inlineScript , params); 156 ScriptScoreFunctionBuilder scriptScoreFunctionBuilder = ScoreFunctionBuilders.scriptFunction(script); 157 //searchRequest.setQuery(functionScoreQuery(QueryBuilders.matchQuery("name","中华").operator(Operator.AND),scriptScoreFunctionBuilder)); 158 searchRequest.setQuery(bean.getQuery()!=null?QueryBuilders.matchQuery("full_name",bean.getQuery()):QueryBuilders.matchAllQuery()); 159 160 BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); 161 BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); 162 //条件 163 boolQueryBuilder.must(queryBuilder); 164 //动态添加聚合项目 165 if (bean.getFacetFields()!=null){ 166 167 for (String field : bean.getFacetFields()) { 168 TermsAggregationBuilder aggFieldBuilder = AggregationBuilders.terms(field).field(field); 169 aggFieldBuilder.size(1000); 170 AggregationBuilder filter = AggregationBuilders.filter(field, boolQueryBuilder); 171 filter.subAggregation(aggFieldBuilder); 172 searchRequest.addAggregation(filter); 173 } 174 } 175 176 177 RangeAggregationBuilder rangeAggregationBuilder = AggregationBuilders.range("range").field("product_sale_price").addRange(0, 30).addRange(30,50).addRange(50,100); 178 searchRequest.addAggregation(rangeAggregationBuilder); 179 searchRequest.setPostFilter(boolQueryBuilder); 180 searchRequest.setFrom(0); 181 searchRequest.setSize(10); 182 searchRequest.setExplain(true); 183 System.out.println("param:"+searchRequest); 184 SearchResponse searchResponse = searchRequest.get(); 185 return searchResponse; 186 187 } 188 189 private QueryBuilder getFilterQuery(String fieldName, Object[] fieldValues, String andor, BoolQueryBuilder queryBuilder) { 190 //BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); 191 192 for (int i = 0; i < fieldValues.length; i++) { 193 if ("OR".equals(andor)){ 194 queryBuilder.should(QueryBuilders.matchQuery(fieldName,fieldValues[i]).operator(Operator.OR)); 195 }else if ("AND".equals(andor)){ 196 queryBuilder.must(QueryBuilders.matchQuery(fieldName,fieldValues[i]).operator(Operator.AND)); 197 } 198 } 199 200 return queryBuilder; 201 202 } 203 204 private void assemQueryParam(SearchBean bean, SearchReturn returns) { 205 SearchParams params = new SearchParams(); 206 params.setKeyword(bean.getQuery()); 207 Filter f = bean.getFilter(); 208 if (f != null) { 209 String[] catFirst = f.getCatFirst(); 210 String[] catSecond = f.getCatSecond(); 211 String[] catThird = f.getCatThird(); 212 Integer[] brand = f.getBrand(); 213 Integer[] country = f.getCountry(); 214 String[] fgCatFirst = f.getFgCatFirst(); 215 String[] fgCatSecond = f.getFgCatSecond(); 216 String[] fgCatThird = f.getFgCatThird(); 217 String[] whiteShopIds = f.getWhiteShopIds(); 218 String[] whiteCateIds = f.getWhiteCateIds(); 219 String[] whiteBrandIds = f.getWhiteBrandIds(); 220 String[] whiteProdIds = f.getWhiteProdIds(); 221 String[] blackShopIds = f.getBlackShopIds(); 222 String[] blackCateIds = f.getBlackCateIds(); 223 String[] blackBrandIds = f.getBlackBrandIds(); 224 String[] blackProdIds = f.getBlackProdIds(); 225 String[] activityIds = f.getActivityIds(); 226 227 if (catFirst != null && catFirst.length > 0) { 228 params.setCatFirst(catFirst); 229 } 230 if (catSecond != null && catSecond.length > 0) { 231 params.setCatSecond(catSecond); 232 } 233 if (catThird != null && catThird.length > 0) { 234 params.setCatThird(catThird); 235 } 236 if (fgCatFirst != null && fgCatFirst.length > 0) { 237 params.setFgCatFirst(fgCatFirst); 238 } 239 if (fgCatSecond != null && fgCatSecond.length > 0) { 240 params.setFgCatSecond(fgCatSecond); 241 } 242 if (fgCatThird != null && fgCatThird.length > 0) { 243 params.setFgCatThird(fgCatThird); 244 } 245 if (brand != null && brand.length > 0) { 246 params.setBrand(brand); 247 } 248 if (country != null && country.length > 0) { 249 params.setCountry(country); 250 } 251 if (activityIds!=null&&activityIds.length>0){ 252 params.setActivityIds(activityIds); 253 } 254 } 255 returns.setSearchParams(params); 256 } 257 }
5.通过kibana查询结果
查询条件 : 跟java执行是一样的参数
1 GET gome_market/_search 2 { 3 "from" : 0, 4 "size" : 10, 5 "query" : { 6 "match" : { 7 "full_name" : { 8 "query" : "多颜色多版本", 9 "operator" : "OR", 10 "prefix_length" : 0, 11 "max_expansions" : 50, 12 "fuzzy_transpositions" : true, 13 "lenient" : false, 14 "zero_terms_query" : "NONE", 15 "boost" : 1.0 16 } 17 } 18 }, 19 "post_filter" : { 20 "bool" : { 21 "must" : [ 22 { 23 "bool" : { 24 "adjust_pure_negative" : true, 25 "boost" : 1.0 26 } 27 } 28 ], 29 "adjust_pure_negative" : true, 30 "boost" : 1.0 31 } 32 }, 33 "explain" : true, 34 "aggregations" : { 35 "category_third" : { 36 "filter" : { 37 "bool" : { 38 "must" : [ 39 { 40 "bool" : { 41 "adjust_pure_negative" : true, 42 "boost" : 1.0 43 } 44 } 45 ], 46 "adjust_pure_negative" : true, 47 "boost" : 1.0 48 } 49 }, 50 "aggregations" : { 51 "category_third" : { 52 "terms" : { 53 "field" : "category_third", 54 "size" : 1000, 55 "min_doc_count" : 1, 56 "shard_min_doc_count" : 0, 57 "show_term_doc_count_error" : false, 58 "order" : [ 59 { 60 "_count" : "desc" 61 }, 62 { 63 "_key" : "asc" 64 } 65 ] 66 } 67 } 68 } 69 }, 70 "category_third_id" : { 71 "filter" : { 72 "bool" : { 73 "must" : [ 74 { 75 "bool" : { 76 "adjust_pure_negative" : true, 77 "boost" : 1.0 78 } 79 } 80 ], 81 "adjust_pure_negative" : true, 82 "boost" : 1.0 83 } 84 }, 85 "aggregations" : { 86 "category_third_id" : { 87 "terms" : { 88 "field" : "category_third_id", 89 "size" : 1000, 90 "min_doc_count" : 1, 91 "shard_min_doc_count" : 0, 92 "show_term_doc_count_error" : false, 93 "order" : [ 94 { 95 "_count" : "desc" 96 }, 97 { 98 "_key" : "asc" 99 } 100 ] 101 } 102 } 103 } 104 }, 105 "dynamicFields.sku级多选_sku_attr" : { 106 "filter" : { 107 "bool" : { 108 "must" : [ 109 { 110 "bool" : { 111 "adjust_pure_negative" : true, 112 "boost" : 1.0 113 } 114 } 115 ], 116 "adjust_pure_negative" : true, 117 "boost" : 1.0 118 } 119 }, 120 "aggregations" : { 121 "dynamicFields.sku级多选_sku_attr" : { 122 "terms" : { 123 "field" : "dynamicFields.sku级多选_sku_attr", 124 "size" : 1000, 125 "min_doc_count" : 1, 126 "shard_min_doc_count" : 0, 127 "show_term_doc_count_error" : false, 128 "order" : [ 129 { 130 "_count" : "desc" 131 }, 132 { 133 "_key" : "asc" 134 } 135 ] 136 } 137 } 138 } 139 }, 140 "dynamicFields.sku级枚举_sku_attr" : { 141 "filter" : { 142 "bool" : { 143 "must" : [ 144 { 145 "bool" : { 146 "adjust_pure_negative" : true, 147 "boost" : 1.0 148 } 149 } 150 ], 151 "adjust_pure_negative" : true, 152 "boost" : 1.0 153 } 154 }, 155 "aggregations" : { 156 "dynamicFields.sku级枚举_sku_attr" : { 157 "terms" : { 158 "field" : "dynamicFields.sku级枚举_sku_attr", 159 "size" : 1000, 160 "min_doc_count" : 1, 161 "shard_min_doc_count" : 0, 162 "show_term_doc_count_error" : false, 163 "order" : [ 164 { 165 "_count" : "desc" 166 }, 167 { 168 "_key" : "asc" 169 } 170 ] 171 } 172 } 173 } 174 }, 175 "dynamicFields.品牌_sku_attr" : { 176 "filter" : { 177 "bool" : { 178 "must" : [ 179 { 180 "bool" : { 181 "adjust_pure_negative" : true, 182 "boost" : 1.0 183 } 184 } 185 ], 186 "adjust_pure_negative" : true, 187 "boost" : 1.0 188 } 189 }, 190 "aggregations" : { 191 "dynamicFields.品牌_sku_attr" : { 192 "terms" : { 193 "field" : "dynamicFields.品牌_sku_attr", 194 "size" : 1000, 195 "min_doc_count" : 1, 196 "shard_min_doc_count" : 0, 197 "show_term_doc_count_error" : false, 198 "order" : [ 199 { 200 "_count" : "desc" 201 }, 202 { 203 "_key" : "asc" 204 } 205 ] 206 } 207 } 208 } 209 }, 210 "dynamicFields.类别-模板2使用_sku_attr" : { 211 "filter" : { 212 "bool" : { 213 "must" : [ 214 { 215 "bool" : { 216 "adjust_pure_negative" : true, 217 "boost" : 1.0 218 } 219 } 220 ], 221 "adjust_pure_negative" : true, 222 "boost" : 1.0 223 } 224 }, 225 "aggregations" : { 226 "dynamicFields.类别-模板2使用_sku_attr" : { 227 "terms" : { 228 "field" : "dynamicFields.类别-模板2使用_sku_attr", 229 "size" : 1000, 230 "min_doc_count" : 1, 231 "shard_min_doc_count" : 0, 232 "show_term_doc_count_error" : false, 233 "order" : [ 234 { 235 "_count" : "desc" 236 }, 237 { 238 "_key" : "asc" 239 } 240 ] 241 } 242 } 243 } 244 }, 245 "dynamicFields.颜色-模板2使用_sku_attr" : { 246 "filter" : { 247 "bool" : { 248 "must" : [ 249 { 250 "bool" : { 251 "adjust_pure_negative" : true, 252 "boost" : 1.0 253 } 254 } 255 ], 256 "adjust_pure_negative" : true, 257 "boost" : 1.0 258 } 259 }, 260 "aggregations" : { 261 "dynamicFields.颜色-模板2使用_sku_attr" : { 262 "terms" : { 263 "field" : "dynamicFields.颜色-模板2使用_sku_attr", 264 "size" : 1000, 265 "min_doc_count" : 1, 266 "shard_min_doc_count" : 0, 267 "show_term_doc_count_error" : false, 268 "order" : [ 269 { 270 "_count" : "desc" 271 }, 272 { 273 "_key" : "asc" 274 } 275 ] 276 } 277 } 278 } 279 }, 280 "range" : { 281 "range" : { 282 "field" : "product_sale_price", 283 "ranges" : [ 284 { 285 "from" : 0.0, 286 "to" : 30.0 287 }, 288 { 289 "from" : 30.0, 290 "to" : 50.0 291 }, 292 { 293 "from" : 50.0, 294 "to" : 100.0 295 } 296 ], 297 "keyed" : false 298 } 299 } 300 } 301 }
查询结果:
1 { 2 "took": 9, 3 "timed_out": false, 4 "_shards": { 5 "total": 5, 6 "successful": 5, 7 "skipped": 0, 8 "failed": 0 9 }, 10 "hits": { 11 "total": 3, 12 "max_score": 4.531806, 13 "hits": [ 14 { 15 "_shard": "[gome_market][0]", 16 "_node": "WBp9VADzRG2Jr-yIKi8h6w", 17 "_index": "gome_market", 18 "_type": "goods", 19 "_id": "100253641", 20 "_score": 4.531806, 21 "_source": { 22 "is_shelves": false, 23 "shop_flag": 2, 24 "category_third": "536_耳机/耳麦", 25 "shop": "", 26 "product_ch": "zyl-多颜色多版本", 27 "spu_score": 0, 28 "category_second": "311_时尚数码", 29 "category_third_id": "536", 30 "id": "100253641", 31 "is_in_store": false, 32 "sku": "100253641", 33 "brand": "10000073_诺基亚(NOKIA)", 34 "is_self": false, 35 "is_suit": false, 36 "product_proto_price": 0, 37 "create_time": "2017-12-25T07:20:37.510Z", 38 "good_comment_rate": 0, 39 "sale_num": 0, 40 "adver": "", 41 "attr_name": [ 42 "品牌_sku_attr", 43 "颜色-模板2使用_sku_attr", 44 "类别-模板2使用_sku_attr", 45 "sku级枚举_sku_attr", 46 "sku级多选_sku_attr" 47 ], 48 "category_first_id": "286", 49 "is_sku": true, 50 "dynamicFields": { 51 "品牌_sku_attr": [ 52 "诺基亚(NOKIA)" 53 ], 54 "颜色-模板2使用_sku_attr": [ 55 "黑色" 56 ], 57 "适用人群-模板2使用_sku_attr": [ 58 "人群" 59 ], 60 "类别-模板2使用_sku_attr": [ 61 "手提包, 洗漱包" 62 ] 63 }, 64 "brand_id": 10000073, 65 "product_img": "//gfs17.atguat.net.cn/T1.FKTBvVT1RCvBVdK", 66 "product_sale_price": 2223, 67 "category_first": "286_数码", 68 "shop_id": "null", 69 "category_second_id": "311", 70 "gome_sku": "1000101403", 71 "spu": "9010006069" 72 }, 73 "_explanation": { 74 "value": 4.531806, 75 "description": "sum of:", 76 "details": [ 77 { 78 "value": 0.9293165, 79 "description": "weight(full_name:多 in 0) [PerFieldSimilarity], result of:", 80 "details": [ 81 { 82 "value": 0.9293165, 83 "description": "score(doc=0,freq=2.0 = termFreq=2.0\n), product of:", 84 "details": [ 85 { 86 "value": 0.6931472, 87 "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:", 88 "details": [ 89 { 90 "value": 1, 91 "description": "docFreq", 92 "details": [] 93 }, 94 { 95 "value": 2, 96 "description": "docCount", 97 "details": [] 98 } 99 ] 100 }, 101 { 102 "value": 1.3407203, 103 "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:", 104 "details": [ 105 { 106 "value": 2, 107 "description": "termFreq=2.0", 108 "details": [] 109 }, 110 { 111 "value": 1.2, 112 "description": "parameter k1", 113 "details": [] 114 }, 115 { 116 "value": 0.75, 117 "description": "parameter b", 118 "details": [] 119 }, 120 { 121 "value": 11, 122 "description": "avgFieldLength", 123 "details": [] 124 }, 125 { 126 "value": 12, 127 "description": "fieldLength", 128 "details": [] 129 } 130 ] 131 } 132 ] 133 } 134 ] 135 }, 136 { 137 "value": 0.6682933, 138 "description": "weight(full_name:颜 in 0) [PerFieldSimilarity], result of:", 139 "details": [ 140 { 141 "value": 0.6682933, 142 "description": "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:", 143 "details": [ 144 { 145 "value": 0.6931472, 146 "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:", 147 "details": [ 148 { 149 "value": 1, 150 "description": "docFreq", 151 "details": [] 152 }, 153 { 154 "value": 2, 155 "description": "docCount", 156 "details": [] 157 } 158 ] 159 }, 160 { 161 "value": 0.96414346, 162 "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:", 163 "details": [ 164 { 165 "value": 1, 166 "description": "termFreq=1.0", 167 "details": [] 168 }, 169 { 170 "value": 1.2, 171 "description": "parameter k1", 172 "details": [] 173 }, 174 { 175 "value": 0.75, 176 "description": "parameter b", 177 "details": [] 178 }, 179 { 180 "value": 11, 181 "description": "avgFieldLength", 182 "details": [] 183 }, 184 { 185 "value": 12, 186 "description": "fieldLength", 187 "details": [] 188 } 189 ] 190 } 191 ] 192 } 193 ] 194 }, 195 { 196 "value": 0.6682933, 197 "description": "weight(full_name:色 in 0) [PerFieldSimilarity], result of:", 198 "details": [ 199 { 200 "value": 0.6682933, 201 "description": "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:", 202 "details": [ 203 { 204 "value": 0.6931472, 205 "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:", 206 "details": [ 207 { 208 "value": 1, 209 "description": "docFreq", 210 "details": [] 211 }, 212 { 213 "value": 2, 214 "description": "docCount", 215 "details": [] 216 } 217 ] 218 }, 219 { 220 "value": 0.96414346, 221 "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:", 222 "details": [ 223 { 224 "value": 1, 225 "description": "termFreq=1.0", 226 "details": [] 227 }, 228 { 229 "value": 1.2, 230 "description": "parameter k1", 231 "details": [] 232 }, 233 { 234 "value": 0.75, 235 "description": "parameter b", 236 "details": [] 237 }, 238 { 239 "value": 11, 240 "description": "avgFieldLength", 241 "details": [] 242 }, 243 { 244 "value": 12, 245 "description": "fieldLength", 246 "details": [] 247 } 248 ] 249 } 250 ] 251 } 252 ] 253 }, 254 { 255 "value": 0.9293165, 256 "description": "weight(full_name:多 in 0) [PerFieldSimilarity], result of:", 257 "details": [ 258 { 259 "value": 0.9293165, 260 "description": "score(doc=0,freq=2.0 = termFreq=2.0\n), product of:", 261 "details": [ 262 { 263 "value": 0.6931472, 264 "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:", 265 "details": [ 266 { 267 "value": 1, 268 "description": "docFreq", 269 "details": [] 270 }, 271 { 272 "value": 2, 273 "description": "docCount", 274 "details": [] 275 } 276 ] 277 }, 278 { 279 "value": 1.3407203, 280 "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:", 281 "details": [ 282 { 283 "value": 2, 284 "description": "termFreq=2.0", 285 "details": [] 286 }, 287 { 288 "value": 1.2, 289 "description": "parameter k1", 290 "details": [] 291 }, 292 { 293 "value": 0.75, 294 "description": "parameter b", 295 "details": [] 296 }, 297 { 298 "value": 11, 299 "description": "avgFieldLength", 300 "details": [] 301 }, 302 { 303 "value": 12, 304 "description": "fieldLength", 305 "details": [] 306 } 307 ] 308 } 309 ] 310 } 311 ] 312 }, 313 { 314 "value": 0.6682933, 315 "description": "weight(full_name:版 in 0) [PerFieldSimilarity], result of:", 316 "details": [ 317 { 318 "value": 0.6682933, 319 "description": "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:", 320 "details": [ 321 { 322 "value": 0.6931472, 323 "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:", 324 "details": [ 325 { 326 "value": 1, 327 "description": "docFreq", 328 "details": [] 329 }, 330 { 331 "value": 2, 332 "description": "docCount", 333 "details": [] 334 } 335 ] 336 }, 337 { 338 "value": 0.96414346, 339 "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:", 340 "details": [ 341 { 342 "value": 1, 343 "description": "termFreq=1.0", 344 "details": [] 345 }, 346 { 347 "value": 1.2, 348 "description": "parameter k1", 349 "details": [] 350 }, 351 { 352 "value": 0.75, 353 "description": "parameter b", 354 "details": [] 355 }, 356 { 357 "value": 11, 358 "description": "avgFieldLength", 359 "details": [] 360 }, 361 { 362 "value": 12, 363 "description": "fieldLength", 364 "details": [] 365 } 366 ] 367 } 368 ] 369 } 370 ] 371 }, 372 { 373 "value": 0.6682933, 374 "description": "weight(full_name:本 in 0) [PerFieldSimilarity], result of:", 375 "details": [ 376 { 377 "value": 0.6682933, 378 "description": "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:", 379 "details": [ 380 { 381 "value": 0.6931472, 382 "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:", 383 "details": [ 384 { 385 "value": 1, 386 "description": "docFreq", 387 "details": [] 388 }, 389 { 390 "value": 2, 391 "description": "docCount", 392 "details": [] 393 } 394 ] 395 }, 396 { 397 "value": 0.96414346, 398 "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:", 399 "details": [ 400 { 401 "value": 1, 402 "description": "termFreq=1.0", 403 "details": [] 404 }, 405 { 406 "value": 1.2, 407 "description": "parameter k1", 408 "details": [] 409 }, 410 { 411 "value": 0.75, 412 "description": "parameter b", 413 "details": [] 414 }, 415 { 416 "value": 11, 417 "description": "avgFieldLength", 418 "details": [] 419 }, 420 { 421 "value": 12, 422 "description": "fieldLength", 423 "details": [] 424 } 425 ] 426 } 427 ] 428 } 429 ] 430 } 431 ] 432 } 433 }, 434 { 435 "_shard": "[gome_market][1]", 436 "_node": "WBp9VADzRG2Jr-yIKi8h6w", 437 "_index": "gome_market", 438 "_type": "goods", 439 "_id": "1000122353", 440 "_score": 0.2876821, 441 "_source": { 442 "is_shelves": false, 443 "shop_flag": 2, 444 "category_third": "536_耳机/耳麦", 445 "shop": "", 446 "product_ch": "诺基亚(NOKIA)C5-05手机(黑银色)非定制机-------9010006069这个product改的", 447 "spu_score": 0, 448 "category_second": "311_时尚数码", 449 "category_third_id": "536", 450 "id": "1000122353", 451 "is_in_store": true, 452 "sku": "1000122353", 453 "brand": "10000073_诺基亚(NOKIA)", 454 "is_self": false, 455 "is_suit": false, 456 "product_proto_price": 0, 457 "create_time": "2017-12-25T07:20:36.931Z", 458 "good_comment_rate": 0, 459 "sale_num": 0, 460 "adver": "%E7%99%BD%E6%8B%BF009%20%E6%B1%89%E5%AD%97", 461 "attr_name": [ 462 "品牌_sku_attr", 463 "颜色-模板2使用_sku_attr", 464 "类别-模板2使用_sku_attr", 465 "sku级枚举_sku_attr", 466 "sku级多选_sku_attr" 467 ], 468 "category_first_id": "286", 469 "is_sku": true, 470 "dynamicFields": { 471 "sku级枚举_sku_attr": [ 472 "洁厕剂" 473 ], 474 "sku级多选_sku_attr": [ 475 "中端高性价比" 476 ], 477 "品牌_sku_attr": [ 478 "诺基亚(NOKIA)" 479 ], 480 "cy-屏幕尺寸_sku_attr": [ 481 "测试测试" 482 ], 483 "0122-cy-多选使用_sku_attr": [ 484 "手柄可折叠" 485 ], 486 "0121-cy-枚举使用_sku_attr": [ 487 "1千米" 488 ], 489 "0121-cy-多选使用_sku_attr": [ 490 "5ml及以下" 491 ], 492 "product级枚举_sku_attr": [ 493 "可组合" 494 ], 495 "product级描述_sku_attr": [ 496 "测试" 497 ] 498 }, 499 "brand_id": 10000073, 500 "product_img": "//gfs11.atguat.net.cn/T1jzhTByY_1RCvBVdK", 501 "product_sale_price": 1311, 502 "category_first": "286_数码", 503 "shop_id": "null", 504 "category_second_id": "311", 505 "gome_sku": "1000046768", 506 "spu": "9010006069" 507 }, 508 "_explanation": { 509 "value": 0.2876821, 510 "description": "sum of:", 511 "details": [ 512 { 513 "value": 0.2876821, 514 "description": "weight(full_name:色 in 0) [PerFieldSimilarity], result of:", 515 "details": [ 516 { 517 "value": 0.2876821, 518 "description": "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:", 519 "details": [ 520 { 521 "value": 0.2876821, 522 "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:", 523 "details": [ 524 { 525 "value": 1, 526 "description": "docFreq", 527 "details": [] 528 }, 529 { 530 "value": 1, 531 "description": "docCount", 532 "details": [] 533 } 534 ] 535 }, 536 { 537 "value": 1, 538 "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:", 539 "details": [ 540 { 541 "value": 1, 542 "description": "termFreq=1.0", 543 "details": [] 544 }, 545 { 546 "value": 1.2, 547 "description": "parameter k1", 548 "details": [] 549 }, 550 { 551 "value": 0.75, 552 "description": "parameter b", 553 "details": [] 554 }, 555 { 556 "value": 26, 557 "description": "avgFieldLength", 558 "details": [] 559 }, 560 { 561 "value": 26, 562 "description": "fieldLength", 563 "details": [] 564 } 565 ] 566 } 567 ] 568 } 569 ] 570 } 571 ] 572 } 573 }, 574 { 575 "_shard": "[gome_market][3]", 576 "_node": "WBp9VADzRG2Jr-yIKi8h6w", 577 "_index": "gome_market", 578 "_type": "goods", 579 "_id": "1000122354", 580 "_score": 0.2876821, 581 "_source": { 582 "is_shelves": false, 583 "shop_flag": 2, 584 "category_third": "536_耳机/耳麦", 585 "shop": "", 586 "product_ch": "诺基亚(NOKIA)C5-05手机(黑红色)searchadmin", 587 "spu_score": 0, 588 "category_second": "311_时尚数码", 589 "category_third_id": "536", 590 "id": "1000122354", 591 "is_in_store": true, 592 "sku": "1000122354", 593 "brand": "10000073_诺基亚(NOKIA)", 594 "is_self": false, 595 "is_suit": false, 596 "product_proto_price": 0, 597 "create_time": "2017-12-25T07:20:38.606Z", 598 "good_comment_rate": 0, 599 "sale_num": 0, 600 "adver": "%E9%95%BF%E6%9C%9F%E4%BF%83%E9%94%80%E8%AF%AD", 601 "attr_name": [ 602 "品牌_sku_attr", 603 "颜色-模板2使用_sku_attr", 604 "类别-模板2使用_sku_attr", 605 "sku级枚举_sku_attr", 606 "sku级多选_sku_attr" 607 ], 608 "category_first_id": "286", 609 "is_sku": true, 610 "dynamicFields": { 611 "品牌_sku_attr": [ 612 "诺基亚(NOKIA)" 613 ], 614 "颜色-模板2使用_sku_attr": [ 615 "黑色" 616 ], 617 "适用人群-模板2使用_sku_attr": [ 618 "人群" 619 ], 620 "类别-模板2使用_sku_attr": [ 621 "马夹包, 腰挂, 手提包, 洗漱包, 化妆包, 折叠包, 其他" 622 ] 623 }, 624 "brand_id": 10000073, 625 "product_img": "//gfs17.atguat.net.cn/T1hNJTB5Av1RCvBVdK", 626 "product_sale_price": 849, 627 "category_first": "286_数码", 628 "shop_id": "null", 629 "category_second_id": "311", 630 "gome_sku": "1000046769", 631 "spu": "9010006069" 632 }, 633 "_explanation": { 634 "value": 0.2876821, 635 "description": "sum of:", 636 "details": [ 637 { 638 "value": 0.2876821, 639 "description": "weight(full_name:色 in 0) [PerFieldSimilarity], result of:", 640 "details": [ 641 { 642 "value": 0.2876821, 643 "description": "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:", 644 "details": [ 645 { 646 "value": 0.2876821, 647 "description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:", 648 "details": [ 649 { 650 "value": 1, 651 "description": "docFreq", 652 "details": [] 653 }, 654 { 655 "value": 1, 656 "description": "docCount", 657 "details": [] 658 } 659 ] 660 }, 661 { 662 "value": 1, 663 "description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:", 664 "details": [ 665 { 666 "value": 1, 667 "description": "termFreq=1.0", 668 "details": [] 669 }, 670 { 671 "value": 1.2, 672 "description": "parameter k1", 673 "details": [] 674 }, 675 { 676 "value": 0.75, 677 "description": "parameter b", 678 "details": [] 679 }, 680 { 681 "value": 17, 682 "description": "avgFieldLength", 683 "details": [] 684 }, 685 { 686 "value": 17, 687 "description": "fieldLength", 688 "details": [] 689 } 690 ] 691 } 692 ] 693 } 694 ] 695 } 696 ] 697 } 698 } 699 ] 700 }, 701 "aggregations": { 702 "dynamicFields.sku级枚举_sku_attr": { 703 "doc_count": 3, 704 "dynamicFields.sku级枚举_sku_attr": { 705 "doc_count_error_upper_bound": 0, 706 "sum_other_doc_count": 0, 707 "buckets": [ 708 { 709 "key": "洁厕剂", 710 "doc_count": 1 711 } 712 ] 713 } 714 }, 715 "dynamicFields.类别-模板2使用_sku_attr": { 716 "doc_count": 3, 717 "dynamicFields.类别-模板2使用_sku_attr": { 718 "doc_count_error_upper_bound": 0, 719 "sum_other_doc_count": 0, 720 "buckets": [ 721 { 722 "key": "手提包, 洗漱包", 723 "doc_count": 1 724 }, 725 { 726 "key": "马夹包, 腰挂, 手提包, 洗漱包, 化妆包, 折叠包, 其他", 727 "doc_count": 1 728 } 729 ] 730 } 731 }, 732 "category_third_id": { 733 "doc_count": 3, 734 "category_third_id": { 735 "doc_count_error_upper_bound": 0, 736 "sum_other_doc_count": 0, 737 "buckets": [ 738 { 739 "key": "536", 740 "doc_count": 3 741 } 742 ] 743 } 744 }, 745 "category_third": { 746 "doc_count": 3, 747 "category_third": { 748 "doc_count_error_upper_bound": 0, 749 "sum_other_doc_count": 0, 750 "buckets": [ 751 { 752 "key": "536_耳机/耳麦", 753 "doc_count": 3 754 } 755 ] 756 } 757 }, 758 "dynamicFields.sku级多选_sku_attr": { 759 "doc_count": 3, 760 "dynamicFields.sku级多选_sku_attr": { 761 "doc_count_error_upper_bound": 0, 762 "sum_other_doc_count": 0, 763 "buckets": [ 764 { 765 "key": "中端高性价比", 766 "doc_count": 1 767 } 768 ] 769 } 770 }, 771 "dynamicFields.品牌_sku_attr": { 772 "doc_count": 3, 773 "dynamicFields.品牌_sku_attr": { 774 "doc_count_error_upper_bound": 0, 775 "sum_other_doc_count": 0, 776 "buckets": [ 777 { 778 "key": "诺基亚(NOKIA)", 779 "doc_count": 3 780 } 781 ] 782 } 783 }, 784 "range": { 785 "buckets": [ 786 { 787 "key": "0.0-30.0", 788 "from": 0, 789 "to": 30, 790 "doc_count": 0 791 }, 792 { 793 "key": "30.0-50.0", 794 "from": 30, 795 "to": 50, 796 "doc_count": 0 797 }, 798 { 799 "key": "50.0-100.0", 800 "from": 50, 801 "to": 100, 802 "doc_count": 0 803 } 804 ] 805 }, 806 "dynamicFields.颜色-模板2使用_sku_attr": { 807 "doc_count": 3, 808 "dynamicFields.颜色-模板2使用_sku_attr": { 809 "doc_count_error_upper_bound": 0, 810 "sum_other_doc_count": 0, 811 "buckets": [ 812 { 813 "key": "黑色", 814 "doc_count": 2 815 } 816 ] 817 } 818 } 819 } 820 }
如果生命没有遗憾,没有波澜