Add support for compound queries
This commit adds support for the compound queries "bool", "boosting", "constant_score" and "dis_max". The "function_score" query is not supported yet. Compound queries are simple. They act just like simple queries, except that they are recursive, wrapping other simple/compound queries. For example: esquery.Bool(). Must(Term("user", "kimchy"), Term("author", "kimchy")). Filter(Term("tag", "tech"))
This commit is contained in:
parent
9ef149ec94
commit
6c8e71c188
|
@ -0,0 +1,61 @@
|
||||||
|
package esquery
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Boolean Queries
|
||||||
|
* https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
type BoolQuery struct {
|
||||||
|
params boolQueryParams
|
||||||
|
}
|
||||||
|
|
||||||
|
type boolQueryParams struct {
|
||||||
|
Must []json.Marshaler `json:"must,omitempty"`
|
||||||
|
Filter []json.Marshaler `json:"filter,omitempty"`
|
||||||
|
MustNot []json.Marshaler `json:"must_not,omitempty"`
|
||||||
|
Should []json.Marshaler `json:"should,omitempty"`
|
||||||
|
MinimumShouldMatch int16 `json:"minimum_should_match,omitempty"`
|
||||||
|
Boost float32 `json:"boost,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Bool() *BoolQuery {
|
||||||
|
return &BoolQuery{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoolQuery) Must(must ...json.Marshaler) *BoolQuery {
|
||||||
|
q.params.Must = append(q.params.Must, must...)
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoolQuery) Filter(filter ...json.Marshaler) *BoolQuery {
|
||||||
|
q.params.Filter = append(q.params.Filter, filter...)
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoolQuery) MustNot(mustnot ...json.Marshaler) *BoolQuery {
|
||||||
|
q.params.MustNot = append(q.params.MustNot, mustnot...)
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoolQuery) Should(should ...json.Marshaler) *BoolQuery {
|
||||||
|
q.params.Should = append(q.params.Should, should...)
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoolQuery) MinimumShouldMatch(val int16) *BoolQuery {
|
||||||
|
q.params.MinimumShouldMatch = val
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoolQuery) Boost(val float32) *BoolQuery {
|
||||||
|
q.params.Boost = val
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q BoolQuery) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(map[string]boolQueryParams{
|
||||||
|
"bool": q.params,
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package esquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBool(t *testing.T) {
|
||||||
|
runTests(t, []queryTest{
|
||||||
|
{
|
||||||
|
"bool with only a simple must",
|
||||||
|
Bool().Must(Term("tag", "tech")),
|
||||||
|
"{\"bool\":{\"must\":[{\"term\":{\"tag\":{\"value\":\"tech\"}}}]}}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bool which must match_all and filter",
|
||||||
|
Bool().Must(MatchAll()).Filter(Term("status", "active")),
|
||||||
|
"{\"bool\":{\"must\":[{\"match_all\":{}}],\"filter\":[{\"term\":{\"status\":{\"value\":\"active\"}}}]}}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bool with a lot of stuff",
|
||||||
|
Bool().
|
||||||
|
Must(Term("user", "kimchy")).
|
||||||
|
Filter(Term("tag", "tech")).
|
||||||
|
MustNot(Range("age").Gte(10).Lte(20)).
|
||||||
|
Should(Term("tag", "wow"), Term("tag", "elasticsearch")).
|
||||||
|
MinimumShouldMatch(1).
|
||||||
|
Boost(1.1),
|
||||||
|
"{\"bool\":{\"must\":[{\"term\":{\"user\":{\"value\":\"kimchy\"}}}],\"filter\":[{\"term\":{\"tag\":{\"value\":\"tech\"}}}],\"must_not\":[{\"range\":{\"age\":{\"gte\":10,\"lte\":20}}}],\"should\":[{\"term\":{\"tag\":{\"value\":\"wow\"}}},{\"term\":{\"tag\":{\"value\":\"elasticsearch\"}}}],\"minimum_should_match\":1,\"boost\":1.1}}\n",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package esquery
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Boosting Queries
|
||||||
|
* https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-boosting-query.html
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
type BoostingQuery struct {
|
||||||
|
params boostingQueryParams
|
||||||
|
}
|
||||||
|
|
||||||
|
type boostingQueryParams struct {
|
||||||
|
Positive json.Marshaler `json:"positive"`
|
||||||
|
Negative json.Marshaler `json:"negative"`
|
||||||
|
NegativeBoost float32 `json:"negative_boost"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Boosting() *BoostingQuery {
|
||||||
|
return &BoostingQuery{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoostingQuery) Positive(p json.Marshaler) *BoostingQuery {
|
||||||
|
q.params.Positive = p
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoostingQuery) Negative(p json.Marshaler) *BoostingQuery {
|
||||||
|
q.params.Negative = p
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoostingQuery) NegativeBoost(b float32) *BoostingQuery {
|
||||||
|
q.params.NegativeBoost = b
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *BoostingQuery) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(map[string]boostingQueryParams{
|
||||||
|
"boosting": q.params,
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package esquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBoost(t *testing.T) {
|
||||||
|
runTests(t, []queryTest{
|
||||||
|
{
|
||||||
|
"boosting query",
|
||||||
|
Boosting().
|
||||||
|
Positive(Term("text", "apple")).
|
||||||
|
Negative(Term("text", "pie tart")).
|
||||||
|
NegativeBoost(0.5),
|
||||||
|
"{\"boosting\":{\"positive\":{\"term\":{\"text\":{\"value\":\"apple\"}}},\"negative\":{\"term\":{\"text\":{\"value\":\"pie tart\"}}},\"negative_boost\":0.5}}\n",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package esquery
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type ConstantScoreQuery struct {
|
||||||
|
params constantScoreParams
|
||||||
|
}
|
||||||
|
|
||||||
|
type constantScoreParams struct {
|
||||||
|
Filter json.Marshaler `json:"filter"`
|
||||||
|
Boost float32 `json:"boost,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConstantScore(filter json.Marshaler) *ConstantScoreQuery {
|
||||||
|
return &ConstantScoreQuery{
|
||||||
|
params: constantScoreParams{Filter: filter},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *ConstantScoreQuery) Boost(b float32) *ConstantScoreQuery {
|
||||||
|
q.params.Boost = b
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q ConstantScoreQuery) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(map[string]constantScoreParams{
|
||||||
|
"constant_score": q.params,
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package esquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConstantScore(t *testing.T) {
|
||||||
|
runTests(t, []queryTest{
|
||||||
|
{
|
||||||
|
"constant_score query without boost",
|
||||||
|
ConstantScore(Term("user", "kimchy")),
|
||||||
|
"{\"constant_score\":{\"filter\":{\"term\":{\"user\":{\"value\":\"kimchy\"}}}}}\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant_score query with boost",
|
||||||
|
ConstantScore(Term("user", "kimchy")).Boost(2.2),
|
||||||
|
"{\"constant_score\":{\"filter\":{\"term\":{\"user\":{\"value\":\"kimchy\"}}},\"boost\":2.2}}\n",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package esquery
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
type DisMaxQuery struct {
|
||||||
|
params disMaxParams
|
||||||
|
}
|
||||||
|
|
||||||
|
type disMaxParams struct {
|
||||||
|
Queries []json.Marshaler `json:"queries"`
|
||||||
|
TieBreaker float32 `json:"tie_breaker,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func DisMax(queries ...json.Marshaler) *DisMaxQuery {
|
||||||
|
return &DisMaxQuery{
|
||||||
|
params: disMaxParams{
|
||||||
|
Queries: queries,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *DisMaxQuery) TieBreaker(b float32) *DisMaxQuery {
|
||||||
|
q.params.TieBreaker = b
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q DisMaxQuery) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(map[string]disMaxParams{
|
||||||
|
"dis_max": q.params,
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package esquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDisMax(t *testing.T) {
|
||||||
|
runTests(t, []queryTest{
|
||||||
|
{
|
||||||
|
"dis_max",
|
||||||
|
DisMax(Term("title", "Quick pets"), Term("body", "Quick pets")).TieBreaker(0.7),
|
||||||
|
"{\"dis_max\":{\"queries\":[{\"term\":{\"title\":{\"value\":\"Quick pets\"}}},{\"term\":{\"body\":{\"value\":\"Quick pets\"}}}],\"tie_breaker\":0.7}}\n",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue