You've already forked multi-select-facet
mirror of
https://github.com/stevenferrer/multi-select-facet.git
synced 2025-11-23 21:54:45 +02:00
277 lines
6.1 KiB
Go
277 lines
6.1 KiB
Go
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)
|
|
}
|
|
}
|