樂優(yōu)商城學習筆記十七-搜索過濾(二)


title: 樂優(yōu)商城學習筆記十七-搜索過濾(二)
date: 2019-04-20 14:37:56
tags:
- 樂優(yōu)商城
- java
- springboot
categories:
- 樂優(yōu)商城


3.生成規(guī)格參數(shù)過濾

3.1.謀而后動

有四個問題需要先思考清楚:

  • 什么時候顯示規(guī)格參數(shù)過濾宦芦?
  • 如何知道哪些規(guī)格需要過濾弧轧?
  • 要過濾的參數(shù)问畅,其可選值是如何獲取的谍失?
  • 規(guī)格過濾的可選值夭咬,其數(shù)據(jù)格式怎樣的?

什么情況下顯示有關(guān)規(guī)格參數(shù)的過濾僧须?

如果用戶尚未選擇商品分類图仓,或者聚合得到的分類數(shù)大于1,那么就沒必要進行規(guī)格參數(shù)的聚合揭厚。因為不同分類的商品却特,其規(guī)格是不同的。

因此筛圆,我們在后臺需要對聚合得到的商品分類數(shù)量進行判斷裂明,如果等于1,我們才繼續(xù)進行規(guī)格參數(shù)的聚合太援。

如何知道哪些規(guī)格需要過濾漾岳?

我們不能把數(shù)據(jù)庫中的所有規(guī)格參數(shù)都拿來過濾。因為并不是所有的規(guī)格參數(shù)都可以用來過濾粉寞,參數(shù)的值是不確定的尼荆。

值的慶幸的是,我們在設計規(guī)格參數(shù)時唧垦,已經(jīng)標記了某些規(guī)格可搜索捅儒,某些不可搜索。

因此,一旦商品分類確定巧还,我們就可以根據(jù)商品分類查詢到其對應的規(guī)格鞭莽,從而知道哪些規(guī)格要進行搜索。

要過濾的參數(shù)麸祷,其可選值是如何獲取的澎怒?

雖然數(shù)據(jù)庫中有所有的規(guī)格參數(shù),但是不能把一切數(shù)據(jù)都用來供用戶選擇阶牍。

與商品分類和品牌一樣喷面,應該是從用戶搜索得到的結(jié)果中聚合,得到與結(jié)果品牌的規(guī)格參數(shù)可選值走孽。

規(guī)格過濾的可選值惧辈,其數(shù)據(jù)格式怎樣的?

我們直接看頁面效果:

1526805322441

我們之前存儲時已經(jīng)將數(shù)據(jù)分段磕瓷,恰好符合這里的需求

3.3.實戰(zhàn)

接下來盒齿,我們就用代碼實現(xiàn)剛才的思路。

總結(jié)一下困食,應該是以下幾步:

  • 1)用戶搜索得到商品边翁,并聚合出商品分類
  • 2)判斷分類數(shù)量是否等于1,如果是則進行規(guī)格參數(shù)聚合
  • 3)先根據(jù)分類硕盹,查找可以用來搜索的規(guī)格
  • 4)對規(guī)格參數(shù)進行聚合
  • 5)將規(guī)格參數(shù)聚合結(jié)果整理后返回

3.3.1.擴展返回結(jié)果

返回結(jié)果中需要增加新數(shù)據(jù)符匾,用來保存規(guī)格參數(shù)過濾條件。這里與前面的品牌和分類過濾的json結(jié)構(gòu)類似:

[
    {
        "k":"規(guī)格參數(shù)名",
        "options":["規(guī)格參數(shù)值","規(guī)格參數(shù)值"]
    }
]

因此莱睁,在java中我們用List<Map<String,Object>>來表示。

/**
 * @Author smallmartial
 * @Date 2019/4/19
 * @Email smallmarital@qq.com
 */
@Data
public class SearchResult extends PageResult<Goods> {

    private List<Category> categories;//分類過濾條件

    private List<Brand> brands;//品牌過濾條件

    private List<Map<String,Object>> specs; // 規(guī)格參數(shù)過濾條件

    public SearchResult(){}

    public SearchResult(Long total, Integer totalPage, List<Goods> item, List<Category> categories, List<Brand> brands, List<Map<String, Object>> specs) {
        super(total, totalPage, item);
        this.categories = categories;
        this.brands = brands;
        this.specs = specs;
    }
}

3.3.2.判斷是否需要聚合

首先芒澜,在聚合得到商品分類后仰剿,判斷分類的個數(shù),如果是1個則進行規(guī)格聚合:

    if (categories !=null && categories.size() == 1){
         specs = buildSpecificationAgg(categories.get(0).getId(),basicQuery);

        }

我們將聚合的代碼抽取到了一個buildSpecificationAgg方法中痴晦。

3.3.3.獲取需要聚合的規(guī)格參數(shù)

然后南吮,我們需要根據(jù)商品分類,查詢所有可用于搜索的規(guī)格參數(shù):

        List<SpecParam> params = specificationClient.querySpecSpecParam(null, cid, true, null);

要注意的是誊酌,這里我們需要根據(jù)id查詢規(guī)格部凑,而規(guī)格參數(shù)接口需要從商品微服務提供

商品微服務:ly-item-interface中提供接口:

@RequestMapping("spec")
public interface SpecificationApi {

    @GetMapping("/params")
    List<SpecParam> querySpecParam(SpecParam specParam);
}

搜索服務中調(diào)用:

@FeignClient("item-service")
public interface SpecificationClient extends SpecificationApi {
}

3.3.4.聚合規(guī)格參數(shù)

因為規(guī)格參數(shù)保存時不做分詞,因此其名稱會自動帶上一個.keyword后綴:

        for (SpecParam param : params) {
            String name = param.getName();
            queryBuilder.addAggregation(AggregationBuilders.terms(name)
                    .field("specs."+name+".keyword"));
        }

3.3.5.解析聚合結(jié)果

        //解析結(jié)果
       Aggregations aggs = result.getAggregations();
        for (SpecParam param : params) {
            //規(guī)格參數(shù)名
            Map<String,Object> map = new HashMap();

            //準備map
            String name = param.getName();
            map.put("k",name);

            StringTerms terms = (StringTerms) aggs.get(name);
            map.put("options",terms.getBuckets().stream().map(b -> b.getKeyAsString()).collect(Collectors.toList()));
            specs.add(map);
        }

3.3.6.最終的代碼

 /**
     * 聚合規(guī)格參數(shù)查詢
     * @param cid
     * @param basicQuery
     * @return
     */
    private List<Map<String,Object>> buildSpecificationAgg(Long cid, QueryBuilder basicQuery) {
        List<Map<String, Object>> specs = new ArrayList<>();
        //查詢所需要的結(jié)果
        List<SpecParam> params = specificationClient.querySpecSpecParam(null, cid, true, null);
        //聚合
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        //帶上查詢條件
        queryBuilder.withQuery(basicQuery);
        for (SpecParam param : params) {
            String name = param.getName();
            queryBuilder.addAggregation(AggregationBuilders.terms(name)
                    .field("specs."+name+".keyword"));
        }
        //獲取結(jié)果
        AggregatedPage<Goods> result = template.queryForPage(queryBuilder.build(), Goods.class);
        // 查詢
        //解析結(jié)果
       Aggregations aggs = result.getAggregations();
        for (SpecParam param : params) {
            //規(guī)格參數(shù)名
            Map<String,Object> map = new HashMap();

            //準備map
            String name = param.getName();
            map.put("k",name);
            
            StringTerms terms = (StringTerms) aggs.get(name);
            map.put("options",terms.getBuckets().stream().map(b -> b.getKeyAsString()).collect(Collectors.toList()));
            specs.add(map);
        }

        return specs;
    }

結(jié)果


1526836458716

3.4.2.展示或收起過濾條件

是不是感覺顯示的太多了碧浊,我們可以通過按鈕點擊來展開和隱藏部分內(nèi)容:

1526836575516

我們在data中定義變量涂邀,記錄展開或隱藏的狀態(tài):

1526837203921

然后在按鈕綁定點擊事件,以改變show的取值:

1526837300139

在展示規(guī)格時箱锐,對show進行判斷:

1528416266890

OK比勉!

4.過濾條件的篩選

當我們點擊頁面的過濾項,要做哪些事情?

  • 把過濾條件保存在search對象中(watch監(jiān)控到search變化后就會發(fā)送到后臺)
  • 在頁面頂部展示已選擇的過濾項
  • 把商品分類展示到頂部面包屑

4.1.保存過濾項

4.1.1.定義屬性

我們把已選擇的過濾項保存在search中:

1526902381310

要注意浩聋,在created構(gòu)造函數(shù)中會對search進行初始化观蜗,所以要在構(gòu)造函數(shù)中對filter進行初始化:

1526902467385

search.filter是一個對象,結(jié)構(gòu):

{
    "過濾項名":"過濾項值"
}

4.1.2.綁定點擊事件

給所有的過濾項綁定點擊事件:

1526902638566

要注意衣洁,點擊事件傳2個參數(shù):

  • k:過濾項的key
  • option:當前過濾項對象

在點擊事件中墓捻,保存過濾項到selectedFilter

selectFilter(k, o){
    const obj = {};
    Object.assign(obj, this.search);
    if(k === 'cid3' || k === 'brandId'){
        o = o.id;
    }
    obj.filter[k] = o;
    this.search = obj;
}

另外,這里search對象中嵌套了filter對象坊夫,請求參數(shù)格式化時需要進行特殊處理砖第,修改common.js中的一段代碼:

1530442052516

我們刷新頁面,點擊后通過瀏覽器功能查看search.filter的屬性變化:

1526904752818

4.2.1.拓展請求對象

我們需要在請求類:SearchRequest中添加屬性践樱,接收過濾屬性厂画。過濾屬性都是鍵值對格式,但是key不確定,所以用一個map來接收即可。

1526910290497

4.2.2.添加過濾條件

目前霍狰,我們的基本查詢是這樣的:

    private QueryBuilder buildBasicQuery(SearchRequest request) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 基本查詢條件
        queryBuilder.must(QueryBuilders.matchQuery("all", request.getKey()).operator(Operator.AND));
        // 過濾條件構(gòu)建器
        BoolQueryBuilder filterQueryBuilder = QueryBuilders.boolQuery();
        // 整理過濾條件
        Map<String, String> filter = request.getFilter();
        for (Map.Entry<String, String> entry : filter.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            // 商品分類和品牌要特殊處理
            if (key != "cid3" && key != "brandId") {
                key = "specs." + key + ".keyword";
            }
            // 字符串類型佳励,進行term查詢
            filterQueryBuilder.must(QueryBuilders.termQuery(key, value));
        }
        // 添加過濾條件
        queryBuilder.filter(filterQueryBuilder);
        return queryBuilder;
    }

總結(jié)

頁面過濾部分功能未能實現(xiàn),點擊品牌分類無法查詢纪蜒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子欲虚,更是在濱河造成了極大的恐慌,老刑警劉巖悔雹,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件复哆,死亡現(xiàn)場離奇詭異,居然都是意外死亡腌零,警方通過查閱死者的電腦和手機梯找,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來益涧,“玉大人锈锤,你說我怎么就攤上這事∠醒” “怎么了久免?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扭弧。 經(jīng)常有香客問我阎姥,道長,這世上最難降的妖魔是什么鸽捻? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任丁寄,我火速辦了婚禮氨淌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伊磺。我一直安慰自己盛正,他們只是感情好,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布屑埋。 她就那樣靜靜地躺著豪筝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摘能。 梳的紋絲不亂的頭發(fā)上续崖,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機與錄音团搞,去河邊找鬼严望。 笑死,一個胖子當著我的面吹牛逻恐,可吹牛的內(nèi)容都是我干的像吻。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼复隆,長吁一口氣:“原來是場噩夢啊……” “哼拨匆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挽拂,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤惭每,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后亏栈,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體台腥,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年绒北,在試婚紗的時候發(fā)現(xiàn)自己被綠了黎侈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡镇饮,死狀恐怖蜓竹,靈堂內(nèi)的尸體忽然破棺而出箕母,到底是詐尸還是另有隱情储藐,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布嘶是,位于F島的核電站钙勃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏聂喇。R本人自食惡果不足惜辖源,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一蔚携、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧克饶,春花似錦酝蜒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至邀跃,卻和暖如春霉咨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拍屑。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工途戒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人僵驰。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓喷斋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親矢渊。 傳聞我的和親對象是個殘疾皇子继准,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容