Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions solr/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,84 @@ func (parser *FireworkResultParser) Parse(resp *[]byte) (FireworkSolrResult, err
return res, err
}

type ExtensiveResultParser struct {
}

func (parser *ExtensiveResultParser) Parse(resp_ *[]byte) (*SolrResult, error) {
sr := &SolrResult{}
jsonbuf, err := bytes2json(resp_)
if err != nil {
return sr, err
}
response := new(SolrResponse)
response.Response = jsonbuf
response.Status = int(jsonbuf["responseHeader"].(map[string]interface{})["status"].(float64))

sr.Results = new(Collection)
sr.Status = response.Status

parser.ParseResponseHeader(response, sr)

if 0 != response.Status {
parser.ParseError(response, sr)
return sr, nil
}

err = parser.ParseResponse(response, sr)

if err != nil {
return nil, err
}

parser.ParseFacets(response, sr)
parser.ParseJsonFacets(response, sr)

return sr, nil
}

func (parser *ExtensiveResultParser) ParseResponseHeader(response *SolrResponse, sr *SolrResult) {
if responseHeader, ok := response.Response["responseHeader"].(map[string]interface{}); ok {
sr.ResponseHeader = responseHeader
}
}

func (parser *ExtensiveResultParser) ParseError(response *SolrResponse, sr *SolrResult) {
if err, ok := response.Response["error"].(map[string]interface{}); ok {
sr.Error = err
}
}

// ParseJsonFacets will assign facets and build sr.jsonfacets if there is a facet_counts
func (parser *ExtensiveResultParser) ParseFacets(response *SolrResponse, sr *SolrResult) {
if fc, ok := response.Response["facet_counts"].(map[string]interface{}); ok {
sr.FacetCounts = fc
if f, ok := fc["facet_fields"].(map[string]interface{}); ok {
sr.Facets = f
}
}
}

// ParseJsonFacets will assign facets and build sr.jsonfacets if there is a facets
func (parser *ExtensiveResultParser) ParseJsonFacets(response *SolrResponse, sr *SolrResult) {
if jf, ok := response.Response["facets"].(map[string]interface{}); ok {
sr.JsonFacets = jf
}
}

// ParseSolrResponse will assign result and build sr.docs if there is a response.
// If there is no response or grouped property in response it will return error
func (parser *ExtensiveResultParser) ParseResponse(response *SolrResponse, sr *SolrResult) (err error) {
if resp, ok := response.Response["response"].(map[string]interface{}); ok {
ParseDocResponse(resp, sr.Results)
} else {
err = fmt.Errorf(`Extensive parser can only parse solr response with response object,
ie response.response and response.response.docs. Or grouped response
Please use other parser or implement your own parser`)
}

return err
}

type StandardResultParser struct {
}

Expand Down
11 changes: 10 additions & 1 deletion solr/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@ func BenchmarkFireworkResultParser(b *testing.B) {
parser := FireworkResultParser{}

parser.Parse(&data)
//fmt.Printf("%v\n", d)
}
}

func BenchmarkExtensiveResultParser(b *testing.B) {
data := []byte(`{"responseHeader":{"status":0,"QTime":0,"params":{"start":"0","q":"*:*","wt":"json","rows":"5"}},"response":{"numFound":12508577,"start":0,"docs":[{"id":"P27665908","p_name":"Archer Lady Case for Blackberry Q10","p_price_c":"175000.00,IDR","p_shop_name":"Nisa Toko","p_domain":"nisatoko","p_shop_sd_name":"Bekasi","p_key":"archer-lady-case-for-blackberry-q10","p_file_path":"product-1/2015/12/28/6208975","p_file_name":"6208975_3959f656-cb27-43df-83db-4b1c1455d3ce.jpg","p_id":27665908,"p_child_cat_id":69,"p_shop_id":733718,"p_condition":1,"p_server_id":1,"p_price":175000.0,"p_dep_id":["65","69","66"],"p_best_match_dink":-288.0,"p_best_match_price":4.756962,"_version_":1521775745340276736},{"id":"P27665917","p_name":"shampo zoku penumbuh rambut hitam berkilau","p_price_c":"115000.00,IDR","p_shop_name":"penumbuh rambut sehat10","p_domain":"penumbuhrambut93","p_shop_sd_name":"Surabaya","p_key":"shampo-zoku-penumbuh-rambut-hitam-berkilau","p_file_path":"product-1/2015/12/28/6766154","p_file_name":"6766154_3344bc2d-8069-4ef6-adc7-7de90b6604f5.jpg","p_id":27665917,"p_child_cat_id":436,"p_shop_id":801110,"p_condition":1,"p_server_id":1,"p_price":115000.0,"p_dep_id":["433","61","436"],"p_best_match_dink":-288.0,"p_best_match_price":4.939302,"_version_":1521775745341325313},{"id":"P27665953","p_name":"Archer Lady Case for HTC One M7","p_price_c":"175000.00,IDR","p_shop_name":"Nisa Toko","p_domain":"nisatoko","p_shop_sd_name":"Bekasi","p_key":"archer-lady-case-for-htc-one-m7","p_file_path":"product-1/2015/12/28/6208975","p_file_name":"6208975_68882b13-3e53-431b-bd64-d2e518db03e9.jpg","p_id":27665953,"p_child_cat_id":69,"p_shop_id":733718,"p_condition":1,"p_server_id":1,"p_price":175000.0,"p_dep_id":["65","69","66"],"p_best_match_dink":-288.0,"p_best_match_price":4.756962,"_version_":1521775745341325315},{"id":"P27665898","p_name":"Archer Lady Case for Blackberry 9900 9980","p_price_c":"175000.00,IDR","p_shop_name":"Nisa Toko","p_domain":"nisatoko","p_shop_sd_name":"Bekasi","p_key":"archer-lady-case-for-blackberry-9900-9980","p_file_path":"product-1/2015/12/28/6208975","p_file_name":"6208975_b40a60e6-1909-4a13-9d49-f881d3a8c5da.jpg","p_id":27665898,"p_child_cat_id":69,"p_shop_id":733718,"p_condition":1,"p_server_id":1,"p_price":175000.0,"p_dep_id":["65","69","66"],"p_best_match_dink":-288.0,"p_best_match_price":4.756962,"_version_":1521775745342373888},{"id":"P27665910","p_name":"VAMPIRE SERUM 30ml ORIGINAL","p_price_c":"26600.00,IDR","p_shop_name":"Dokter Cantikku","p_domain":"doktercantiku","p_shop_sd_name":"Jakarta","p_key":"vampire-serum-30ml-original","p_file_path":"product-1/2015/12/28/6634788","p_file_name":"6634788_e34791af-a170-48e8-b836-68da4c5d775a.jpg","p_id":27665910,"p_child_cat_id":598,"p_shop_id":785036,"p_condition":1,"p_server_id":1,"p_price":26600.0,"p_dep_id":["61","445","598"],"p_best_match_dink":-288.0,"p_best_match_price":5.5751185,"_version_":1521775745342373889}]}}`)

for i := 0; i < b.N; i++ {
parser := FireworkResultParser{}

parser.Parse(&data)
}
}

Expand Down
31 changes: 31 additions & 0 deletions solr/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,37 @@ func (q *Query) FieldList(fl string) {
q.params.Add("fl", fl)
}

// f (Facet) https://cwiki.apache.org/confluence/display/solr/Faceting#Faceting-Thefacet.fieldParameter
// Example: category
func (q *Query) AddFacet(f string) {
q.params.Set("facet", "true")
q.params.Add("facet.field", f)
}

// mc (Facet min count) https://cwiki.apache.org/confluence/display/solr/Faceting#Faceting-Thefacet.mincountParameter
// Example: 5
func (q *Query) SetFacetMinCount(mc int) {
q.params.Set("facet.mincount", fmt.Sprintf("%d", mc))
}

// f (Facet) https://wiki.apache.org/solr/SimpleFacetParameters#facet.pivot
// Example: category
func (q *Query) AddFacetPivot(f string) {
q.params.Add("facet.pivot", f)
}

// mc (Facet pivot min count) https://wiki.apache.org/solr/SimpleFacetParameters#facet.pivot
// Example: 5
func (q *Query) SetFacetPivotMinCount(mc int) {
q.params.Set("facet.pivot.mincount", fmt.Sprintf("%d", mc))
}

// jf (Json facet) https://cwiki.apache.org/confluence/display/solr/JSON+Request+API#JSONRequestAPI-FacetExample
// Example: {avg_price:"avg(price)"}
func (q *Query) AddJsonFacet(jf string) {
q.params.Add("json.facet", jf)
}

// geofilt - The distance filter http://wiki.apache.org/solr/SpatialSearch
// Output example: fq={!geofilt pt=45.15,-93.85 sfield=store d=5}
func (q *Query) Geofilt(latitude, longitude float64, sfield string, distance float64) {
Expand Down
51 changes: 51 additions & 0 deletions solr/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,54 @@ func TestQueryQueryField(t *testing.T) {
}
}

func TestSolrQueryAddFacet(t *testing.T) {
q := NewQuery()
q.AddFacet("color")
q.AddFacet("size")
expected := "facet=true&facet.field=color&facet.field=size"
result := q.String()
if result != expected {
t.Errorf("expected '%s' but got '%s'", expected, result)
}
}

func TestSolrQuerySetFacetMinCount(t *testing.T) {
q := NewQuery()
q.SetFacetMinCount(10)
expected := "facet.mincount=10"
result := q.String()
if result != expected {
t.Errorf("expected '%s' but got '%s'", expected, result)
}
}

func TestSolrQueryAddFacetPivot(t *testing.T) {
q := NewQuery()
q.AddFacetPivot("color")
q.AddFacetPivot("size")
expected := "facet.pivot=color&facet.pivot=size"
result := q.String()
if result != expected {
t.Errorf("expected '%s' but got '%s'", expected, result)
}
}

func TestSolrQuerySetFacetPivotMinCount(t *testing.T) {
q := NewQuery()
q.SetFacetPivotMinCount(10)
expected := "facet.pivot.mincount=10"
result := q.String()
if result != expected {
t.Errorf("expected '%s' but got '%s'", expected, result)
}
}

func TestSolrQueryAddJsonFacet(t *testing.T) {
q := NewQuery()
q.AddJsonFacet("{categories:{type:terms,field:cat,sort:'x desc',facet:{x:'avg(price)',y:'sum(price)'}}")
expected := "json.facet=%7Bcategories%3A%7Btype%3Aterms%2Cfield%3Acat%2Csort%3A%27x+desc%27%2Cfacet%3A%7Bx%3A%27avg%28price%29%27%2Cy%3A%27sum%28price%29%27%7D%7D"
result := q.String()
if result != expected {
t.Errorf("expected '%s' but got '%s'", expected, result)
}
}
2 changes: 2 additions & 0 deletions solr/solr.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ type SolrResult struct {
Results *Collection // results parsed documents, basically response object
QTime int
ResponseHeader map[string]interface{}
Facets map[string]interface{}
JsonFacets map[string]interface{}
FacetCounts map[string]interface{}
Highlighting map[string]interface{}
Error map[string]interface{}
Expand Down