商品搜索完全实现代码

 @Override
    public Map searchSkuInfoByEs(Map<String, String> searchmap) {
        Map map=new HashMap<>();
        //条件对象  目标:为了合并 搜索条件及排序及分页及高亮
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        //组合条件对象
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        //本次查询关键词
        if(null!=searchmap.get("keywords") && !"".equals(searchmap.get("keywords").trim())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("name",searchmap.get("keywords")).operator(Operator.AND));
        }
        else {
       //默认搜索条件
        }
        //本次查询品牌
        if(null!=searchmap.get("brand")&&!"".equals(searchmap.get("brand").trim())){
           boolQueryBuilder.filter(QueryBuilders.termQuery("brandName",searchmap.get("brand")));
        }
        //本次规格查询
        Set<Map.Entry<String, String>> entries = searchmap.entrySet();
        if(null!=entries&&entries.size()>0){
            for (Map.Entry<String, String> entry : entries) {
                if(entry.getKey().startsWith("spec_")){
                    //feign传值会去掉特殊符号,这里 转下
                    String replace = entry.getValue().replace("%2B", "+");
                    boolQueryBuilder.filter(QueryBuilders.termQuery("specMap."+entry.getKey().substring(5)+".keyword",replace));
                }
            }
        }

        //本次价格查询
        //价格区间  500-1000  3000
        if (null != searchmap.get("price") && !"".equals(searchmap.get("price").trim())) {
            String[] prices = searchmap.get("price").split("-");
            if(prices.length==2){
                //>=    <
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(prices[0]).lt(prices[1]));
            }
            else if(prices.length==1){
                //>=
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(prices[0]));
            }
        }


        //高亮
        HighlightBuilder.Field highName = new HighlightBuilder.Field("name");
        highName.preTags("<span style='color:red'>");
        highName.postTags("</span>");
        nativeSearchQueryBuilder.withHighlightFields(highName);

        //排序
        //sortRule=ASC&sortField=price
        if (null != searchmap.get("sortRule") && !"".equals(searchmap.get("sortRule"))) {
            if("ASC".equals(searchmap.get("sortRule"))){
                nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(searchmap.get("sortField")).order(SortOrder.ASC));
            }
            else {
                nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(searchmap.get("sortField")).order(SortOrder.DESC));
            }
        }

       //分页
        String pageNum=searchmap.get("pageNum");
        if(StringUtils.isEmpty(pageNum)){
             pageNum="1";
        }
        nativeSearchQueryBuilder.withPageable(PageRequest.of(Integer.valueOf(pageNum)-1,Page.pageSize));
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);


       //品牌集合查询
        //设置别名
        String skuBrandName="skuBrandName";
        TermsAggregationBuilder brandName = AggregationBuilders.terms(skuBrandName).field("brandName");
        //放到原生对象
        nativeSearchQueryBuilder.addAggregation(brandName);


        //规格集合查询查询
        String specName="specName";
        TermsAggregationBuilder specNameBuilder = AggregationBuilders.terms(specName).field("spec.keyword");
        nativeSearchQueryBuilder.addAggregation(specNameBuilder);

        AggregatedPage<SkuInfo> page = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), SkuInfo.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                List<T> content = new ArrayList<>();

                //总条数
//                "hits": {
//                    "total": 90830,
//                            "max_score": 1,
//                            "hits": [
//                    {
//                        "_index": ".kibana",
//                            "_type": "config",
//                            "_id": "5.6.8",
//                            "_score": 1,
//                            "_source": {
//                        "buildNum": 15616,
//                                "defaultIndex": "AWvrbNEDfJIoQxXR4Osp"
//                    }
//                    },
                SearchHits hits = searchResponse.getHits();
                //"hits": [
                ////                    {
                ////                        "_index": ".kibana",
                ////                            "_type": "config",
                ////                            "_id": "5.6.8",
                ////                            "_score": 1,
                ////                            "_source": {
                ////                        "buildNum": 15616,
                ////                                "defaultIndex": "AWvrbNEDfJIoQxXR4Osp"
                ////                    }
                ///.....搜索到的所有信息都在这个数组里 ,下面得到他
                SearchHit[] hits1 = hits.getHits();
                //遍历每条信息
                for (SearchHit documentFields : hits1) {

                 /*           { "id": 27598311688,
                                    "name": "小米(MI) 小米6X 手机 全网通 手机 曜石黑 6GB 128GB",
                                    "price": 61900,
                                    "num": 10000,
                                    "image": "https://m.360buyimg.com/mobilecms/s720x720_jfs/t1/15859/22/1559/207576/5c136ab1E271f0be2/8d8e5e8dce11aea2.jpg!q70.jpg.webp",
                                    "status": "1",
                                    "createTime": 1556668800000,
                                    "updateTime": 1556668800000,
                                    "isDefault": null,
                                    "spuId": 2759831168300,
                                    "categoryId": 0,
                                    "categoryName": "手机",
                                    "brandName": "小米",
                                    "spec": """{"颜色": "红色", "版本": "6GB+128GB"}""",
                                    "specMap": {
                                "颜色": "红色",
                                        "版本": "6GB+128GB"
                            }*/
                     //得到搜索信息的json串
                    String sourceAsString = documentFields.getSourceAsString();
                    //转为对象
                    SkuInfo skuInfo = JSON.parseObject(sourceAsString, SkuInfo.class);

                    //判断是否有高亮的值
                    //k:name v:GOGER远近两用老花镜男多焦点看高清双光<span style='color:red'>眼</span>架 看远看近300度(建议65~69岁)
                    //可能有多个字段需要高亮所以用map放
                    Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
                    if(null != highlightFields && highlightFields.size() > 0){
                        //得到name字段获取高亮信息
                        HighlightField highlightField = highlightFields.get("name");
                        //GOGER远近两用老花镜男多焦点看高清双光<span style='color:red'>眼</span>架 看远看近300度(建议65~69岁)
                        Text[] fragments = highlightField.getFragments();
                        if(null != fragments && fragments.length > 0){
                            //把高亮完的放到skuInfo
                            String hname = fragments[0].toString();
                            skuInfo.setName(hname);
                        }
                    }


                    content.add((T)skuInfo);

                }

                long totalHits = hits.totalHits;
                Aggregations aggregations = searchResponse.getAggregations();
                //结果集
                //分页
                //分组
                //需要用到的对象丢到里面
                return new AggregatedPageImpl<T>(content,pageable,totalHits,aggregations);
            }
        });

        //拿品牌集合
        Terms aggregations =(Terms) page.getAggregation(skuBrandName);
        //得到品牌集合
        List<String> brandNamecollect = aggregations.getBuckets().stream().map(c -> ((Terms.Bucket) c).getKeyAsString()).collect(toList());
         //得到规格集合
        Terms specNameAgg =(Terms)page.getAggregation(specName);
        List<String> specNamecollect = specNameAgg.getBuckets().stream().map(c -> ((Terms.Bucket) c).getKeyAsString()).collect(toList());
        Map<String,Set<String>> specMap=buildModel(specNamecollect);

        List<SkuInfo> content = page.getContent();
        map.put("rows",content);
        map.put("pageNum",pageNum);
        map.put("total",page.getTotalElements());
        map.put("brandList",brandNamecollect);
        map.put("specList",specMap);
        return map;
    }

    private Map<String,Set<String>> buildModel(List<String> specNamecollect) {
        Map<String,Set<String>> map=null;
        if(null!=specNamecollect&&specNamecollect.size()>0){
            map=new HashMap<>();
            for (String spec : specNamecollect) {
                Map<String,String> jsonMap = JSON.parseObject(spec, Map.class);
                Set<Map.Entry<String, String>> entries = jsonMap.entrySet();
                for (Map.Entry<String, String> entry : entries) {
                    Set<String> set=map.get(entry.getKey());
                    if(null==set){
                        set=new HashSet<>();
                    }
                    set.add(entry.getValue());
                    map.put(entry.getKey(),set);
                }
            }
        }
        return map;
    }

controller:

//因为feign方式传参时特殊符号会去掉所以需要用别的东西替换。
 public Map<String,String> handerModel(Map<String,String> searchmap){
        if(null!=searchmap&&searchmap.size()>0){
            Set<Map.Entry<String, String>> entries = searchmap.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                if(entry.getKey().startsWith("spec_")){
                    searchmap.put(entry.getKey(),entry.getValue().replace("+","%2B"));
                }
            }
        }
        return searchmap;
    }
@GetMapping
    public String searchGoods(Model model,@RequestParam Map<String,String> searchmap){
        searchmap=handerModel(searchmap);
        Map map = webSearchService.searchSkuInfoByEs(searchmap);
        model.addAttribute("result",map);
        model.addAttribute("searchMap",searchmap);
        model.addAttribute("page",new Page((int)map.get("total"),Integer.valueOf(map.get("pageNum").toString()),Page.pageSize));
        //http://search.changgou.com:9011/wsearch?keywords=手机
        StringBuilder url = new StringBuilder();
        url.append("http://search.changgou.com:9011/wsearch");
        if(null!=searchmap&&searchmap.size()>0){
            url.append("?");
            Set<Map.Entry<String, String>> entries = searchmap.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                //防止键值对有重复,去掉
                if("pageNum".equals(entry.getKey())||"sortRule".equals(entry.getKey())
                        || "sortField".equals(entry.getKey())){

                }
                else {
                    url.append("&").append(entry.getKey()).append("=").append(entry.getValue());
                }
            }
        }
        model.addAttribute("url",url.toString());
        return "search";
    }

这里需要注意的是Feign方式传参会 去掉特殊符号,比如这里当传4G+64G时,会变为4G 64G,所以传值前要用非特殊符号替代下,接到参时再转回来使用。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容