From 207be3ace32e564a72d0a705728193dbff1583c9 Mon Sep 17 00:00:00 2001 From: Steven Ferrer Date: Sat, 13 Jun 2020 23:21:28 +0800 Subject: [PATCH] dynamic facet configurations --- README.md | 4 +- api/search_handler.go | 276 ----------------------- {api => cmd/api}/.gitignore | 0 {api => cmd/api}/main.go | 44 ++-- api/phones.json => cmd/api/products.json | 58 +++++ cmd/api/sample-query.json | 66 ++++++ cmd/api/search_handler.go | 265 ++++++++++++++++++++++ cmd/api/simplified-query.json | 28 +++ api/go.mod => go.mod | 4 +- api/go.sum => go.sum | 5 + webapp/src/App.vue | 8 +- webapp/src/components/Filters.vue | 2 +- webapp/src/components/Product.vue | 21 +- 13 files changed, 475 insertions(+), 306 deletions(-) delete mode 100644 api/search_handler.go rename {api => cmd/api}/.gitignore (100%) rename {api => cmd/api}/main.go (70%) rename api/phones.json => cmd/api/products.json (77%) create mode 100644 cmd/api/sample-query.json create mode 100644 cmd/api/search_handler.go create mode 100644 cmd/api/simplified-query.json rename api/go.mod => go.mod (71%) rename api/go.sum => go.sum (85%) diff --git a/README.md b/README.md index 2d8fe52..41bc5ed 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Multi-Select Facet Example An example of multi-select facet using [Solr](https://lucene.apache.org/solr), [Vue](https://vuejs.org) and [Go](http://go.dev/). -This example uses [Buefy](http://buefy.org/) components and [solr-go](https://github.com/stevenferrer/solr-go) for interacting with [Solr](https://lucene.apache.org/solr). - +## Running the example +Use docker-compose maybe? ## Contributing Please feel free to improve this by [sending a PR](https://github.com/stevenferrer/multi-select-facet/pulls) or [opening an issue](https://github.com/stevenferrer/multi-select-facet/issues). diff --git a/api/search_handler.go b/api/search_handler.go deleted file mode 100644 index f6a18f7..0000000 --- a/api/search_handler.go +++ /dev/null @@ -1,276 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "net/http" - "strings" - - "github.com/stevenferrer/solr-go" -) - -type facet struct { - Name string `json:"name"` - Buckets []bucket `json:"buckets"` -} - -type bucket struct { - Val string `json:"val"` - SkuCount int `json:"skuCount"` - ProductCount int `json:"productCount"` -} - -type product struct { - ID string `json:"id"` - Name string `json:"name"` - Category string `json:"category"` - ProductType string `json:"productType"` - Brand string `json:"brand"` -} - -type facetConfig struct { - field, facet string - vals []string -} - -type searchHandler struct { - solrClient solr.Client -} - -func (h *searchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - categories := strings.Split(r.URL.Query().Get("categories"), ",") - productTypes := strings.Split(r.URL.Query().Get("productTypes"), ",") - brands := strings.Split(r.URL.Query().Get("brands"), ",") - colorFamilies := strings.Split(r.URL.Query().Get("colorFamilies"), ",") - simCardSlots := strings.Split(r.URL.Query().Get("simCardSlots"), ",") - operatingSystems := strings.Split(r.URL.Query().Get("operatingSystems"), ",") - storageCapacities := strings.Split(r.URL.Query().Get("storageCapacities"), ",") - - facetsMap := M{} - - catsFacetCfg := facetConfig{ - facet: "categories", - field: "category", - vals: categories, - } - - productTypsFacetCfg := facetConfig{ - facet: "productTypes", - field: "productType", - vals: productTypes, - } - - brandsFacetCfg := facetConfig{ - facet: "brands", - field: "brand", - vals: brands, - } - - filters := []string{} - for _, facetCfg := range []facetConfig{catsFacetCfg, productTypsFacetCfg, brandsFacetCfg} { - tagVals := []string{} - for _, val := range facetCfg.vals { - if val == "" { - continue - } - tagVals = append(tagVals, facetCfg.field+":"+val) - } - - if len(tagVals) == 0 { - filters = append(filters, fmt.Sprintf("{!tag=top}%s:*", facetCfg.field)) - } else { - filters = append(filters, fmt.Sprintf("{!tag=top}%s", strings.Join(tagVals, " OR "))) - } - - facetsMap[facetCfg.facet] = M{ - "facet": M{ - "productCount": "uniqueBlock(_root_)", - }, - "field": facetCfg.field, - "limit": -1, - "type": "terms", - } - - } - - colorFamiliesFctCfg := facetConfig{ - facet: "colorFamilies", - field: "colorFamily_s", - vals: colorFamilies, - } - - simCardSlotsFctCfg := facetConfig{ - facet: "simCardSlots", - field: "simCardSlots_s", - vals: simCardSlots, - } - - operatingSystemsFctCfg := facetConfig{ - facet: "operatingSystems", - field: "operatingSystem_s", - vals: operatingSystems, - } - - storageCapacitiesFctCfg := facetConfig{ - facet: "storageCapacities", - field: "storageCapacity_s", - vals: storageCapacities, - } - - childFqs := []string{} - for _, fctCfg := range []facetConfig{colorFamiliesFctCfg, simCardSlotsFctCfg, operatingSystemsFctCfg, storageCapacitiesFctCfg} { - tagVals := []string{} - for _, val := range fctCfg.vals { - if val == "" { - continue - } - tagVals = append(tagVals, fctCfg.field+":"+val) - } - - if len(tagVals) == 0 { - childFqs = append(childFqs, fmt.Sprintf("{!tag=%s}%s:*", fctCfg.field, fctCfg.field)) - } else { - childFqs = append(childFqs, fmt.Sprintf("{!tag=%s}%s", fctCfg.field, strings.Join(tagVals, " OR "))) - } - - facetsMap[fctCfg.facet] = M{ - "domain": M{ - "excludeTags": "top", - "filter": []string{ - fmt.Sprintf("{!filters param=$child.fq excludeTags=%s v=$child.query}", fctCfg.field), - "{!child of=$parent.fq filters=$fq v=$parent.fq}", - }, - }, - "type": "terms", - "field": fctCfg.field, - "limit": -1, - "facet": M{ - "productCount": "uniqueBlock(_root_)", - }, - } - } - - query := M{ - "query": "{!parent tag=top filters=$child.fq which=$parent.fq score=total v=$child.query}", - "queries": M{ - "parent.fq": "docType:product", - "child.query": "docType:sku", - "child.fq": childFqs, - }, - "filter": filters, - "fields": "*", - "facet": facetsMap, - } - - // b, err := json.MarshalIndent(query, "", " ") - // if err != nil { - // log.Fatal(err) - // } - - // fmt.Println(string(b)) - - queryRespone, err := h.solrClient.Query().Query(r.Context(), collection, query) - if err != nil { - http.Error(w, err.Error(), 500) - } - - var facets = []facet{} - for k, v := range queryRespone.Facets { - if k == "count" { - continue - } - - vv, ok := v.(map[string]interface{}) - if !ok { - http.Error(w, "buckets is not map[string]interface{}", 500) - } - - bucks, ok := vv["buckets"].([]interface{}) - if !ok { - http.Error(w, "buckets not found", 500) - } - - buckets := []bucket{} - for _, bk := range bucks { - buck, ok := bk.(map[string]interface{}) - if !ok { - http.Error(w, "buck not map[string]interface{}", 500) - } - - productCount, ok := buck["productCount"].(float64) - if !ok { - http.Error(w, "product count not found", 500) - } - - skuCount, ok := buck["count"].(float64) - if !ok { - http.Error(w, "sku count not found", 500) - } - - val, ok := buck["val"].(string) - if !ok { - http.Error(w, "val not found", 500) - } - - buckets = append(buckets, bucket{ - Val: val, - SkuCount: int(skuCount), - ProductCount: int(productCount), - }) - - } - - facets = append(facets, facet{ - Name: k, - Buckets: buckets, - }) - } - - var products = []product{} - for _, doc := range queryRespone.Response.Docs { - id, ok := doc["id"].(string) - if !ok { - http.Error(w, "id not found", 500) - } - - name, ok := doc["name"].([]interface{}) - if !ok { - http.Error(w, "name not found", 500) - } - - category, ok := doc["category"].([]interface{}) - if !ok { - http.Error(w, "category not found", 500) - } - - brand, ok := doc["brand"].([]interface{}) - if !ok { - http.Error(w, "brand not found", 500) - } - - productType, ok := doc["productType"].(string) - if !ok { - http.Error(w, "productType not found", 500) - } - - products = append(products, product{ - ID: id, - Name: name[0].(string), - Category: category[0].(string), - Brand: brand[0].(string), - ProductType: productType, - }) - } - - resp := M{ - "products": products, - "facets": facets, - "queryResponse": queryRespone, - } - - w.Header().Add("content-type", "application/json") - err = json.NewEncoder(w).Encode(resp) - if err != nil { - http.Error(w, http.StatusText(500), 500) - } -} diff --git a/api/.gitignore b/cmd/api/.gitignore similarity index 100% rename from api/.gitignore rename to cmd/api/.gitignore diff --git a/api/main.go b/cmd/api/main.go similarity index 70% rename from api/main.go rename to cmd/api/main.go index e5633b4..cc48d54 100644 --- a/api/main.go +++ b/cmd/api/main.go @@ -17,16 +17,20 @@ import ( solrschema "github.com/stevenferrer/solr-go/schema" ) -type M = map[string]interface{} +// Any is a convenience type for interface{} +type Any = interface{} + +// Map is a convenience type for map[string]interface{} +type Map = map[string]Any const ( - collection = "multi-select-demo" - dataPath = "phones.json" + dataPath = "products.json" ) func main() { - initSchema := flag.Bool("init-schema", false, "initialize solr schema") - index := flag.Bool("index", false, "index products") + collection := flag.String("collection", "multi-select-demo", "specify the name of collection") + initSchema := flag.Bool("initialize-schema", false, "initialize solr schema") + index := flag.Bool("index-data", false, "index the data") flag.Parse() solrClient := solr.NewClient("localhost", 8983) @@ -34,7 +38,7 @@ func main() { ctx := context.Background() if *initSchema { log.Print("initializing solr schema...") - err := initSolrSchema(ctx, solrClient.Schema()) + err := initSolrSchema(ctx, *collection, solrClient.Schema()) if err != nil { log.Fatal(err) } @@ -42,7 +46,7 @@ func main() { if *index { log.Println("indexing products...") - err := indexProducts(ctx, solrClient.Index()) + err := indexProducts(ctx, *collection, solrClient.Index()) if err != nil { log.Fatal(err) } @@ -63,6 +67,7 @@ func main() { // search handler r.Method(http.MethodGet, "/search", &searchHandler{ + collection: *collection, solrClient: solrClient, }) @@ -74,7 +79,8 @@ func main() { } } -func initSolrSchema(ctx context.Context, schemaClient solrschema.Client) error { +func initSolrSchema(ctx context.Context, collection string, + schemaClient solrschema.Client) error { // define the fields fields := []solrschema.Field{ { @@ -116,31 +122,29 @@ func initSolrSchema(ctx context.Context, schemaClient solrschema.Client) error { } } - // define copy field - err := schemaClient.AddCopyField(ctx, collection, solrschema.CopyField{ - Source: "*", - Dest: "_text_", - }) - if err != nil { - return errors.Wrap(err, "add copy field") - } - return nil } -func indexProducts(ctx context.Context, indexClient solrindex.JSONClient) error { +func indexProducts(ctx context.Context, collection string, + indexClient solrindex.JSONClient) error { b, err := ioutil.ReadFile(dataPath) if err != nil { return err } - var docs []M + var docs []Map err = json.Unmarshal(b, &docs) if err != nil { return err } - err = indexClient.AddMultiple(ctx, collection, docs) + err = indexClient.AddDocs(ctx, collection, docs) + if err != nil { + return err + } + + // commit updates + err = indexClient.Commit(ctx, collection) if err != nil { return err } diff --git a/api/phones.json b/cmd/api/products.json similarity index 77% rename from api/phones.json rename to cmd/api/products.json index f5bc59c..b4ce8f3 100644 --- a/api/phones.json +++ b/cmd/api/products.json @@ -186,5 +186,63 @@ "storageCapacity_s": "128GB" } ] + }, + { + "id": "7", + "name": "Amazon Kindle Paperwhite - 10th Gen", + "brand": "Amazon", + "category": "Electronic Devices", + "productType": "E-reader", + "docType": "product", + "skus": [ + { + "id": "70", + "docType": "sku", + "colorFamily_s": "Black", + "storageCapacity_s": "8GB", + "operatingSystem_s": "Linux" + }, + { + "id": "71", + "docType": "sku", + "colorFamily_s": "Black", + "storageCapacity_s": "32GB", + "operatingSystem_s": "Linux" + } + ] + }, + { + "id": "8", + "name": "Kobo Clara HD 6\" Carta E Ink Touchscreen E-Reader", + "brand": "Kobo", + "category": "Electronic Devices", + "productType": "E-reader", + "docType": "product", + "skus": [ + { + "id": "80", + "docType": "sku", + "colorFamily_s": "Black", + "storageCapacity_s": "8GB", + "operatingSystem_s": "Linux" + } + ] + }, + { + "id": "9", + "name": "Likebook Mars E-Reader, 7.8' Carta Touch Screen", + "brand": "Likebook Mars", + "category": "Electronic Devices", + "productType": "E-reader", + "docType": "product", + "skus": [ + { + "id": "90", + "docType": "sku", + "colorFamily_s": "Black", + "storageCapacity_s": "16GB", + "operatingSystem_s": "Android" + } + ] } ] diff --git a/cmd/api/sample-query.json b/cmd/api/sample-query.json new file mode 100644 index 0000000..a38c04f --- /dev/null +++ b/cmd/api/sample-query.json @@ -0,0 +1,66 @@ +{ + "query": "{!parent tag=top filters=$skuFilters which=$product score=total v=$sku}", + "queries": { + "product": "docType:product", + "sku": "docType:sku", + "skuFilters": [ + "{!tag=colorFamily_s}colorFamily_s:Black", + "{!tag=operatingSystem_s}operatingSystem_s:*", + "{!tag=storageCapacity_s}storageCapacity_s:*" + ] + }, + "filter": ["{!tag=top}productType:*", "{!tag=top}brand:Amazon"], + "facet": { + "Brand": { + "facet": { "productCount": "uniqueBlock(_root_)" }, + "field": "brand", + "limit": -1, + "type": "terms" + }, + "Color Family": { + "domain": { + "excludeTags": "top", + "filter": [ + "{!filters param=$skuFilters excludeTags=colorFamily_s v=$sku}", + "{!child of=$product filters=$fq v=$product}" + ] + }, + "facet": { "productCount": "uniqueBlock(_root_)" }, + "field": "colorFamily_s", + "limit": -1, + "type": "terms" + }, + "Operating System": { + "domain": { + "excludeTags": "top", + "filter": [ + "{!filters param=$skuFilters excludeTags=operatingSystem_s v=$sku}", + "{!child of=$product filters=$fq v=$product}" + ] + }, + "facet": { "productCount": "uniqueBlock(_root_)" }, + "field": "operatingSystem_s", + "limit": -1, + "type": "terms" + }, + "Product Type": { + "facet": { "productCount": "uniqueBlock(_root_)" }, + "field": "productType", + "limit": -1, + "type": "terms" + }, + "Storage Capacity": { + "domain": { + "excludeTags": "top", + "filter": [ + "{!filters param=$skuFilters excludeTags=storageCapacity_s v=$sku}", + "{!child of=$product filters=$fq v=$product}" + ] + }, + "facet": { "productCount": "uniqueBlock(_root_)" }, + "field": "storageCapacity_s", + "limit": -1, + "type": "terms" + } + } +} diff --git a/cmd/api/search_handler.go b/cmd/api/search_handler.go new file mode 100644 index 0000000..c4b3f7b --- /dev/null +++ b/cmd/api/search_handler.go @@ -0,0 +1,265 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" + "strings" + + "github.com/stevenferrer/solr-go" + "github.com/stevenferrer/solr-go/query" +) + +// searchHandler is the search handler +type searchHandler struct { + collection string + solrClient solr.Client +} + +// facetConfig is a facet configuration +type facetConfig struct { + // field is the field name + field, + // facet is the facet name + facet, + // param is the url query param to be used for retrieving filter values + urlParam string + // isChild set to true to indicate that this is a child facet + isChild bool +} + +var facetConfigs = []facetConfig{ + // { + // facet: "Category", + // field: "category", + // urlParam: "categories", + // }, + { + facet: "Product Type", + field: "productType", + urlParam: "productTypes", + }, + { + facet: "Brand", + field: "brand", + urlParam: "brands", + }, + { + facet: "Color Family", + field: "colorFamily_s", + urlParam: "colorFamilies", + isChild: true, + }, + // { + // facet: "Sim Card Slots", + // field: "simCardSlots_s", + // urlParam: "simCardSlots", + // isChild: true, + // }, + { + facet: "Operating System", + field: "operatingSystem_s", + urlParam: "operatingSystems", + isChild: true, + }, + { + facet: "Storage Capacity", + field: "storageCapacity_s", + urlParam: "storageCapacities", + isChild: true, + }, +} + +func (h *searchHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + facetsMap := Map{} + productFilters, skuFilters := []string{}, []string{} + for _, fctCfg := range facetConfigs { + tagVals := []string{} + filterVals := strings.Split(r.URL.Query().Get(fctCfg.urlParam), ",") + for _, val := range filterVals { + if val == "" { + continue + } + tagVals = append(tagVals, fctCfg.field+":"+val) + } + + if !fctCfg.isChild { + // product filters + if len(tagVals) > 0 { + productFilters = append(productFilters, fmt.Sprintf("{!tag=top}%s", strings.Join(tagVals, " OR "))) + } else { + productFilters = append(productFilters, fmt.Sprintf("{!tag=top}%s:*", fctCfg.field)) + } + + facetsMap[fctCfg.facet] = Map{ + "facet": Map{ + "productCount": "uniqueBlock(_root_)", + }, + "field": fctCfg.field, + "limit": -1, + "type": "terms", + } + + continue + } + + // sku filters + if len(tagVals) > 0 { + skuFilters = append(skuFilters, fmt.Sprintf("{!tag=%s}%s", fctCfg.field, strings.Join(tagVals, " OR "))) + } else { + skuFilters = append(skuFilters, fmt.Sprintf("{!tag=%s}%s:*", fctCfg.field, fctCfg.field)) + } + + facetsMap[fctCfg.facet] = Map{ + "domain": Map{ + "excludeTags": "top", + "filter": []string{ + fmt.Sprintf("{!filters param=$skuFilters excludeTags=%s v=$sku}", fctCfg.field), + "{!child of=$product filters=$filter v=$product}", + }, + }, + "type": "terms", + "field": fctCfg.field, + "limit": -1, + "facet": Map{ + "productCount": "uniqueBlock(_root_)", + }, + } + } + + query := Map{ + "query": "{!parent tag=top filters=$skuFilters which=$product score=total v=$sku}", + "queries": Map{ + "product": "docType:product", + "sku": "docType:sku", + "skuFilters": skuFilters, + }, + "filter": productFilters, + "facet": facetsMap, + } + + queryResp, err := h.solrClient.Query().Query(r.Context(), h.collection, query) + if err != nil { + http.Error(w, err.Error(), 500) + return + } + + // extract products and facets from query response + resp, err := buildResp(queryResp) + if err != nil { + http.Error(w, err.Error(), 500) + return + } + + resp["query"] = query + + w.Header().Add("content-type", "application/json") + err = json.NewEncoder(w).Encode(resp) + if err != nil { + http.Error(w, err.Error(), 500) + } +} + +func buildResp(queryResp *query.Response) (Map, error) { + var facets = []Map{} + for name, v := range queryResp.Facets { + if name == "count" { + continue + } + + vv, ok := v.(Map) + if !ok { + return nil, errors.New("v is not M") + } + + bucks, ok := vv["buckets"].([]Any) + if !ok { + return nil, errors.New("vv is not []Any") + } + + buckets := []Map{} + for _, bk := range bucks { + buck, ok := bk.(Map) + if !ok { + return nil, errors.New("bucket is not M") + } + + productCount, ok := buck["productCount"].(float64) + if !ok { + return nil, errors.New("productCount is not float64") + } + + skuCount, ok := buck["count"].(float64) + if !ok { + return nil, errors.New("count is not float64") + } + + val, ok := buck["val"].(string) + if !ok { + return nil, errors.New("val is not string") + } + + buckets = append(buckets, map[string]interface{}{ + "val": val, + "skuCount": int(skuCount), + "productCount": int(productCount), + }) + + } + + var param string + for _, fctCfg := range facetConfigs { + if fctCfg.facet == name { + param = fctCfg.urlParam + } + } + + facets = append(facets, Map{ + "name": name, + "param": param, + "buckets": buckets, + }) + } + + var products = []Map{} + for _, doc := range queryResp.Response.Docs { + id, ok := doc["id"].(string) + if !ok { + return nil, errors.New("id not found or is not string") + } + + name, ok := doc["name"].([]Any) + if !ok { + return nil, errors.New("name not found or is not []Any") + } + + category, ok := doc["category"].([]Any) + if !ok { + return nil, errors.New("category not found or is not []Any") + } + + brand, ok := doc["brand"].([]Any) + if !ok { + return nil, errors.New("brand not found or is not []Any") + } + + productType, ok := doc["productType"].(string) + if !ok { + return nil, errors.New("productType not found or is not string") + } + + products = append(products, Map{ + "id": id, + "name": name[0].(string), + "category": category[0].(string), + "brand": brand[0].(string), + "productType": productType, + }) + } + + return Map{ + "products": products, + "facets": facets, + }, nil +} diff --git a/cmd/api/simplified-query.json b/cmd/api/simplified-query.json new file mode 100644 index 0000000..cdf81be --- /dev/null +++ b/cmd/api/simplified-query.json @@ -0,0 +1,28 @@ +{ + "query": "{!parent tag=top filters=$skuFilters which=docType:product v=docType:sku}", + "queries": { + "skuFilters": ["{!tag=colorFamily_s}colorFamily_s:Black"] + }, + "filter": ["{!tag=top}brand:Amazon"], + "facet": { + "Brand": { + "facet": { "productCount": "uniqueBlock(_root_)" }, + "field": "brand", + "limit": -1, + "type": "terms" + }, + "Color Family": { + "domain": { + "excludeTags": "top", + "filter": [ + "{!filters param=$skuFilters excludeTags=colorFamily_s v=$sku}", + "{!child of=docType:product filters=$filter v=docType:product}" + ] + }, + "facet": { "productCount": "uniqueBlock(_root_)" }, + "field": "colorFamily_s", + "limit": -1, + "type": "terms" + } + } +} diff --git a/api/go.mod b/go.mod similarity index 71% rename from api/go.mod rename to go.mod index fb2ea20..14e9fea 100644 --- a/api/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/stevenferrer/multi-select-facet/api +module github.com/stevenferrer/multi-select-facet go 1.14 @@ -7,6 +7,6 @@ require ( github.com/go-chi/chi v4.1.2+incompatible github.com/go-chi/cors v1.1.1 github.com/pkg/errors v0.9.1 - github.com/stevenferrer/solr-go v0.0.4 + github.com/stevenferrer/solr-go v0.0.6 golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect ) diff --git a/api/go.sum b/go.sum similarity index 85% rename from api/go.sum rename to go.sum index d532fc6..c74d926 100644 --- a/api/go.sum +++ b/go.sum @@ -13,9 +13,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stevenferrer/solr-go v0.0.4 h1:XsUtbAdlX9txVUNWNPwdLoXb7lWBEGGcD4ZLs33ACdE= github.com/stevenferrer/solr-go v0.0.4/go.mod h1:gatY+DJUzNG3NdONghbJa2JJw6ykdECbiYXtiBy7ykY= +github.com/stevenferrer/solr-go v0.0.6 h1:pFludjKdCmQJxJTwmszwRfAvoqDRG/gcYzf3u+rG5wE= +github.com/stevenferrer/solr-go v0.0.6/go.mod h1:ePa8+6kV1baPpoywPbmcR06wQ0500EGuMntYGxli5Xk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -27,3 +30,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/webapp/src/App.vue b/webapp/src/App.vue index 713c73f..4996475 100644 --- a/webapp/src/App.vue +++ b/webapp/src/App.vue @@ -30,7 +30,7 @@ async function search(filters) { const url = new URL("http://localhost:8081/search"); filters.forEach((filter) => { - url.searchParams.append(filter.name, filter.selected.join(",")); + url.searchParams.append(filter.param, filter.selected.join(",")); }); let response = await fetch(url, { @@ -49,7 +49,7 @@ async function search(filters) { facets: facets .map((facet) => { let selected = []; - let filter = filters.find((filter) => filter.name === facet.name); + let filter = filters.find((filter) => filter.param === facet.param); if (filter) { selected = filter.selected; } @@ -96,8 +96,8 @@ export default { const { facets: oldFacet } = this; const filters = oldFacet .filter(({ selected }) => selected.length > 0) - .map(({ name, selected }) => { - return { name, selected }; + .map(({ name, param, selected }) => { + return { name, param, selected }; }); const { products, facets } = await search(filters); diff --git a/webapp/src/components/Filters.vue b/webapp/src/components/Filters.vue index 76ace4a..5fcfc9c 100644 --- a/webapp/src/components/Filters.vue +++ b/webapp/src/components/Filters.vue @@ -1,7 +1,7 @@ + +