From 556f883bf448be22320094a581479404cca04bef Mon Sep 17 00:00:00 2001 From: Oliver Eilhard Date: Sun, 30 Aug 2020 11:59:29 +0200 Subject: [PATCH] Change in RangeQuery from, to, include_lower and include_upper parameters into gt, gte, lt, lte --- client.go | 2 +- search_aggs_bucket_filter_test.go | 6 +- search_aggs_bucket_filters_test.go | 8 +- search_queries_bool_test.go | 2 +- search_queries_boosting_test.go | 2 +- search_queries_nested_test.go | 4 +- search_queries_range.go | 138 +++++++++++++++++++---------- search_queries_range_test.go | 105 ++++++++++++++++------ 8 files changed, 181 insertions(+), 86 deletions(-) diff --git a/client.go b/client.go index 897a6570a..9dd8aa772 100644 --- a/client.go +++ b/client.go @@ -26,7 +26,7 @@ import ( const ( // Version is the current version of Elastic. - Version = "6.2.34" + Version = "6.2.35" // DefaultURL is the default endpoint of Elasticsearch on the local machine. // It is used e.g. when initializing a new Client without a specific URL. diff --git a/search_aggs_bucket_filter_test.go b/search_aggs_bucket_filter_test.go index 6aa4fbb7c..c7b46e4b2 100644 --- a/search_aggs_bucket_filter_test.go +++ b/search_aggs_bucket_filter_test.go @@ -21,7 +21,7 @@ func TestFilterAggregation(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"filter":{"range":{"stock":{"from":0,"include_lower":false,"include_upper":true,"to":null}}}}` + expected := `{"filter":{"range":{"stock":{"gt":0}}}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } @@ -41,7 +41,7 @@ func TestFilterAggregationWithSubAggregation(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"aggregations":{"avg_price":{"avg":{"field":"price"}}},"filter":{"range":{"stock":{"from":0,"include_lower":false,"include_upper":true,"to":null}}}}` + expected := `{"aggregations":{"avg_price":{"avg":{"field":"price"}}},"filter":{"range":{"stock":{"gt":0}}}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } @@ -59,7 +59,7 @@ func TestFilterAggregationWithMeta(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"filter":{"range":{"stock":{"from":0,"include_lower":false,"include_upper":true,"to":null}}},"meta":{"name":"Oliver"}}` + expected := `{"filter":{"range":{"stock":{"gt":0}}},"meta":{"name":"Oliver"}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } diff --git a/search_aggs_bucket_filters_test.go b/search_aggs_bucket_filters_test.go index 6de5758eb..399fc35ec 100644 --- a/search_aggs_bucket_filters_test.go +++ b/search_aggs_bucket_filters_test.go @@ -22,7 +22,7 @@ func TestFiltersAggregationFilters(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"filters":{"filters":[{"range":{"stock":{"from":0,"include_lower":false,"include_upper":true,"to":null}}},{"term":{"symbol":"GOOG"}}]}}` + expected := `{"filters":{"filters":[{"range":{"stock":{"gt":0}}},{"term":{"symbol":"GOOG"}}]}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } @@ -43,7 +43,7 @@ func TestFiltersAggregationFilterWithName(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"filters":{"filters":{"f1":{"range":{"stock":{"from":0,"include_lower":false,"include_upper":true,"to":null}}},"f2":{"term":{"symbol":"GOOG"}}}}}` + expected := `{"filters":{"filters":{"f1":{"range":{"stock":{"gt":0}}},"f2":{"term":{"symbol":"GOOG"}}}}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } @@ -94,7 +94,7 @@ func TestFiltersAggregationWithSubAggregation(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"aggregations":{"avg_price":{"avg":{"field":"price"}}},"filters":{"filters":[{"range":{"stock":{"from":0,"include_lower":false,"include_upper":true,"to":null}}},{"term":{"symbol":"GOOG"}}]}}` + expected := `{"aggregations":{"avg_price":{"avg":{"field":"price"}}},"filters":{"filters":[{"range":{"stock":{"gt":0}}},{"term":{"symbol":"GOOG"}}]}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } @@ -113,7 +113,7 @@ func TestFiltersAggregationWithMetaData(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"filters":{"filters":[{"range":{"stock":{"from":0,"include_lower":false,"include_upper":true,"to":null}}},{"term":{"symbol":"GOOG"}}]},"meta":{"name":"Oliver"}}` + expected := `{"filters":{"filters":[{"range":{"stock":{"gt":0}}},{"term":{"symbol":"GOOG"}}]},"meta":{"name":"Oliver"}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } diff --git a/search_queries_bool_test.go b/search_queries_bool_test.go index cdcc38de1..e772923dd 100644 --- a/search_queries_bool_test.go +++ b/search_queries_bool_test.go @@ -26,7 +26,7 @@ func TestBoolQuery(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"bool":{"_name":"Test","boost":10,"filter":{"term":{"account":"1"}},"must":{"term":{"tag":"wow"}},"must_not":{"range":{"age":{"from":10,"include_lower":true,"include_upper":true,"to":20}}},"should":[{"term":{"tag":"sometag"}},{"term":{"tag":"sometagtag"}}]}}` + expected := `{"bool":{"_name":"Test","boost":10,"filter":{"term":{"account":"1"}},"must":{"term":{"tag":"wow"}},"must_not":{"range":{"age":{"gte":10,"lte":20}}},"should":[{"term":{"tag":"sometag"}},{"term":{"tag":"sometagtag"}}]}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } diff --git a/search_queries_boosting_test.go b/search_queries_boosting_test.go index 6c7f263f4..ca18741df 100644 --- a/search_queries_boosting_test.go +++ b/search_queries_boosting_test.go @@ -23,7 +23,7 @@ func TestBoostingQuery(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"boosting":{"negative":{"range":{"age":{"from":10,"include_lower":true,"include_upper":true,"to":20}}},"negative_boost":0.2,"positive":{"term":{"tag":"wow"}}}}` + expected := `{"boosting":{"negative":{"range":{"age":{"gte":10,"lte":20}}},"negative_boost":0.2,"positive":{"term":{"tag":"wow"}}}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } diff --git a/search_queries_nested_test.go b/search_queries_nested_test.go index c7a5322a6..551967c2a 100644 --- a/search_queries_nested_test.go +++ b/search_queries_nested_test.go @@ -23,7 +23,7 @@ func TestNestedQuery(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"nested":{"_name":"qname","path":"obj1","query":{"bool":{"must":[{"term":{"obj1.name":"blue"}},{"range":{"obj1.count":{"from":5,"include_lower":false,"include_upper":true,"to":null}}}]}}}}` + expected := `{"nested":{"_name":"qname","path":"obj1","query":{"bool":{"must":[{"term":{"obj1.name":"blue"}},{"range":{"obj1.count":{"gt":5}}}]}}}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } @@ -45,7 +45,7 @@ func TestNestedQueryWithInnerHit(t *testing.T) { t.Fatalf("marshaling to JSON failed: %v", err) } got := string(data) - expected := `{"nested":{"_name":"qname","inner_hits":{"name":"comments","query":{"term":{"user":"olivere"}}},"path":"obj1","query":{"bool":{"must":[{"term":{"obj1.name":"blue"}},{"range":{"obj1.count":{"from":5,"include_lower":false,"include_upper":true,"to":null}}}]}}}}` + expected := `{"nested":{"_name":"qname","inner_hits":{"name":"comments","query":{"term":{"user":"olivere"}}},"path":"obj1","query":{"bool":{"must":[{"term":{"obj1.name":"blue"}},{"range":{"obj1.count":{"gt":5}}}]}}}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } diff --git a/search_queries_range.go b/search_queries_range.go index 5bfb2a6f9..6fe50c335 100644 --- a/search_queries_range.go +++ b/search_queries_range.go @@ -4,14 +4,26 @@ package elastic +// https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-range-query.html#querying-range-fields +const ( + // (Default) Matches documents with a range field value that intersects the query’s range. + RelationIntersects string = "INTERSECTS" + // Matches documents with a range field value that entirely contains the query’s range. + RelationContains string = "CONTAINS" + // Matches documents with a range field value entirely within the query’s range. + RelationWithin string = "WITHIN" +) + // RangeQuery matches documents with fields that have terms within a certain range. // -// For details, see +// For details, see Elastic Documentation (6.8): // https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-range-query.html type RangeQuery struct { name string - from interface{} - to interface{} + gt interface{} + gte interface{} + lt interface{} + lte interface{} timeZone string includeLower bool includeUpper bool @@ -26,63 +38,31 @@ func NewRangeQuery(name string) *RangeQuery { return &RangeQuery{name: name, includeLower: true, includeUpper: true} } -// From indicates the from part of the RangeQuery. -// Use nil to indicate an unbounded from part. -func (q *RangeQuery) From(from interface{}) *RangeQuery { - q.from = from - return q -} - // Gt indicates a greater-than value for the from part. // Use nil to indicate an unbounded from part. -func (q *RangeQuery) Gt(from interface{}) *RangeQuery { - q.from = from - q.includeLower = false +func (q *RangeQuery) Gt(gt interface{}) *RangeQuery { + q.gt = gt return q } // Gte indicates a greater-than-or-equal value for the from part. // Use nil to indicate an unbounded from part. -func (q *RangeQuery) Gte(from interface{}) *RangeQuery { - q.from = from - q.includeLower = true - return q -} - -// To indicates the to part of the RangeQuery. -// Use nil to indicate an unbounded to part. -func (q *RangeQuery) To(to interface{}) *RangeQuery { - q.to = to +func (q *RangeQuery) Gte(gte interface{}) *RangeQuery { + q.gte = gte return q } // Lt indicates a less-than value for the to part. // Use nil to indicate an unbounded to part. -func (q *RangeQuery) Lt(to interface{}) *RangeQuery { - q.to = to - q.includeUpper = false +func (q *RangeQuery) Lt(lt interface{}) *RangeQuery { + q.lt = lt return q } // Lte indicates a less-than-or-equal value for the to part. // Use nil to indicate an unbounded to part. -func (q *RangeQuery) Lte(to interface{}) *RangeQuery { - q.to = to - q.includeUpper = true - return q -} - -// IncludeLower indicates whether the lower bound should be included or not. -// Defaults to true. -func (q *RangeQuery) IncludeLower(includeLower bool) *RangeQuery { - q.includeLower = includeLower - return q -} - -// IncludeUpper indicates whether the upper bound should be included or not. -// Defaults to true. -func (q *RangeQuery) IncludeUpper(includeUpper bool) *RangeQuery { - q.includeUpper = includeUpper +func (q *RangeQuery) Lte(lte interface{}) *RangeQuery { + q.lte = lte return q } @@ -114,12 +94,65 @@ func (q *RangeQuery) Format(format string) *RangeQuery { } // Relation is used for range fields. which can be one of -// "within", "contains", "intersects" (default) and "disjoint". +// "within", "contains" and "intersects" (default). func (q *RangeQuery) Relation(relation string) *RangeQuery { q.relation = relation return q } +// From Deprecated use Gt or Gte +func (q *RangeQuery) From(from interface{}) *RangeQuery { + if q.includeLower { + q.gte = from + q.gt = nil + return q + } + q.gte = nil + q.gt = from + return q +} + +// To Deprecated use Lt or Lte +func (q *RangeQuery) To(to interface{}) *RangeQuery { + if q.includeUpper { + q.lte = to + q.lt = nil + return q + } + q.lte = nil + q.lt = to + return q +} + +// IncludeLower Deprecated use Gt or Gte +func (q *RangeQuery) IncludeLower(includeLower bool) *RangeQuery { + if includeLower && q.gt != nil { + q.gte = q.gt + q.gt = nil + } + if !includeLower && q.gte != nil { + q.gt = q.gte + q.gte = nil + } + q.includeLower = includeLower + return q +} + +// IncludeUpper Deprecated use Lt or Lte +func (q *RangeQuery) IncludeUpper(includeUpper bool) *RangeQuery { + if includeUpper && q.lt != nil { + q.lte = q.lt + q.lt = nil + } + if !includeUpper && q.lte != nil { + q.lt = q.lte + q.lte = nil + } + + q.includeUpper = includeUpper + return q +} + // Source returns JSON for the query. func (q *RangeQuery) Source() (interface{}, error) { source := make(map[string]interface{}) @@ -130,8 +163,18 @@ func (q *RangeQuery) Source() (interface{}, error) { params := make(map[string]interface{}) rangeQ[q.name] = params - params["from"] = q.from - params["to"] = q.to + if q.gt != nil { + params["gt"] = q.gt + } + if q.gte != nil { + params["gte"] = q.gte + } + if q.lt != nil { + params["lt"] = q.lt + } + if q.lte != nil { + params["lte"] = q.lte + } if q.timeZone != "" { params["time_zone"] = q.timeZone } @@ -144,9 +187,6 @@ func (q *RangeQuery) Source() (interface{}, error) { if q.boost != nil { params["boost"] = *q.boost } - params["include_lower"] = q.includeLower - params["include_upper"] = q.includeUpper - if q.queryName != "" { rangeQ["_name"] = q.queryName } diff --git a/search_queries_range_test.go b/search_queries_range_test.go index 6ee8c2edc..0e986ab75 100644 --- a/search_queries_range_test.go +++ b/search_queries_range_test.go @@ -10,18 +10,47 @@ import ( ) func TestRangeQuery(t *testing.T) { - q := NewRangeQuery("postDate").From("2010-03-01").To("2010-04-01").Boost(3).Relation("within") - q = q.QueryName("my_query") - src, err := q.Source() - if err != nil { - t.Fatal(err) + q := NewRangeQuery("postDate"). + Gte("2010-03-01") + + got := asJsonString(t, q) + expected := `{"range":{"postDate":{"gte":"2010-03-01"}}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) } - data, err := json.Marshal(src) - if err != nil { - t.Fatalf("marshaling to JSON failed: %v", err) +} + +func TestRangeQueryWithBoost(t *testing.T) { + q := NewRangeQuery("postDate"). + Gte("2010-03-01"). + Boost(3) + + got := asJsonString(t, q) + expected := `{"range":{"postDate":{"boost":3,"gte":"2010-03-01"}}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) } - got := string(data) - expected := `{"range":{"_name":"my_query","postDate":{"boost":3,"from":"2010-03-01","include_lower":true,"include_upper":true,"relation":"within","to":"2010-04-01"}}}` +} + +func TestRangeQueryWithRelation(t *testing.T) { + q := NewRangeQuery("postDate"). + Gte("2010-03-01"). + Relation(RelationWithin) + + got := asJsonString(t, q) + expected := `{"range":{"postDate":{"gte":"2010-03-01","relation":"WITHIN"}}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) + } +} + +func TestRangeQueryWithQueryName(t *testing.T) { + q := NewRangeQuery("postDate"). + Gte("2010-03-01"). + QueryName("queryName") + + got := asJsonString(t, q) + expected := `{"range":{"_name":"queryName","postDate":{"gte":"2010-03-01"}}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } @@ -32,16 +61,9 @@ func TestRangeQueryWithTimeZone(t *testing.T) { Gte("2012-01-01"). Lte("now"). TimeZone("+1:00") - src, err := q.Source() - if err != nil { - t.Fatal(err) - } - data, err := json.Marshal(src) - if err != nil { - t.Fatalf("marshaling to JSON failed: %v", err) - } - got := string(data) - expected := `{"range":{"born":{"from":"2012-01-01","include_lower":true,"include_upper":true,"time_zone":"+1:00","to":"now"}}}` + + got := asJsonString(t, q) + expected := `{"range":{"born":{"gte":"2012-01-01","lte":"now","time_zone":"+1:00"}}}` if got != expected { t.Errorf("expected\n%s\n,got:\n%s", expected, got) } @@ -52,6 +74,43 @@ func TestRangeQueryWithFormat(t *testing.T) { Gte("2012/01/01"). Lte("now"). Format("yyyy/MM/dd") + + got := asJsonString(t, q) + expected := `{"range":{"born":{"format":"yyyy/MM/dd","gte":"2012/01/01","lte":"now"}}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) + } +} + +func TestDeprecatedRangeQueryTransformedIntoGtLt(t *testing.T) { + q := NewRangeQuery("born"). + From("2012/01/01"). + To("now"). + IncludeLower(false). + IncludeUpper(false) + + got := asJsonString(t, q) + expected := `{"range":{"born":{"gt":"2012/01/01","lt":"now"}}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) + } +} + +func TestDeprecatedRangeQueryTransformedIntoGteLte(t *testing.T) { + q := NewRangeQuery("postDate"). + From("2012/01/01"). + To("now"). + IncludeLower(true). + IncludeUpper(true) + + got := asJsonString(t, q) + expected := `{"range":{"postDate":{"gte":"2012/01/01","lte":"now"}}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) + } +} + +func asJsonString(t *testing.T, q *RangeQuery) string { src, err := q.Source() if err != nil { t.Fatal(err) @@ -60,9 +119,5 @@ func TestRangeQueryWithFormat(t *testing.T) { if err != nil { t.Fatalf("marshaling to JSON failed: %v", err) } - got := string(data) - expected := `{"range":{"born":{"format":"yyyy/MM/dd","from":"2012/01/01","include_lower":true,"include_upper":true,"to":"now"}}}` - if got != expected { - t.Errorf("expected\n%s\n,got:\n%s", expected, got) - } + return string(data) }