Compare commits
No commits in common. "master" and "v0.1.0" have entirely different histories.
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
.idea/
|
|
@ -35,7 +35,7 @@ This is an early release, API may still change.
|
|||||||
`esquery` is a Go module. To install, simply run this in your project's root directory:
|
`esquery` is a Go module. To install, simply run this in your project's root directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go get github.com/aquasecurity/esquery/v8
|
go get github.com/aquasecurity/esquery
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -51,8 +51,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/aquasecurity/esquery/v8"
|
"github.com/aquasecurity/esquery"
|
||||||
"github.com/elastic/go-elasticsearch/v8"
|
"github.com/elastic/go-elasticsearch/v7"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -158,7 +158,6 @@ The following aggregations are currently supported:
|
|||||||
| `"string_stats"` | `StringStats()` |
|
| `"string_stats"` | `StringStats()` |
|
||||||
| `"top_hits"` | `TopHits()` |
|
| `"top_hits"` | `TopHits()` |
|
||||||
| `"terms"` | `TermsAgg()` |
|
| `"terms"` | `TermsAgg()` |
|
||||||
| `"date_histogram"` | `DateHistogramAgg()` |
|
|
||||||
|
|
||||||
### Supported Top Level Options
|
### Supported Top Level Options
|
||||||
|
|
||||||
|
@ -61,15 +61,8 @@ func TestAggregations(t *testing.T) {
|
|||||||
{
|
{
|
||||||
"a complex, multi-aggregation, nested",
|
"a complex, multi-aggregation, nested",
|
||||||
Aggregate(
|
Aggregate(
|
||||||
NestedAgg("categories", "categories").
|
NestedAgg("categories","categories").
|
||||||
Aggs(
|
Aggs(TermsAgg("type","outdoors")),
|
||||||
TermsAgg("type", "outdoors").Aggs(
|
|
||||||
DateHistogramAgg("time", "timestamp").
|
|
||||||
Fixedinterval("3m").MinDocCount(0).Aggs(
|
|
||||||
Sum("sumPeople", "people"),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FilterAgg("filtered",
|
FilterAgg("filtered",
|
||||||
Term("type", "t-shirt")),
|
Term("type", "t-shirt")),
|
||||||
),
|
),
|
||||||
@ -79,34 +72,18 @@ func TestAggregations(t *testing.T) {
|
|||||||
"nested": map[string]interface{}{
|
"nested": map[string]interface{}{
|
||||||
"path": "categories",
|
"path": "categories",
|
||||||
},
|
},
|
||||||
"aggs": map[string]interface{}{
|
"aggs": map[string]interface{} {
|
||||||
"type": map[string]interface{}{
|
"type": map[string]interface{} {
|
||||||
"terms": map[string]interface{}{
|
"terms": map[string]interface{} {
|
||||||
"field": "outdoors",
|
"field": "outdoors",
|
||||||
},
|
},
|
||||||
"aggs": map[string]interface{}{
|
|
||||||
"time": map[string]interface{}{
|
|
||||||
"date_histogram": map[string]interface{}{
|
|
||||||
"field": "timestamp",
|
|
||||||
"fixed_interval": "3m",
|
|
||||||
"min_doc_count": 0,
|
|
||||||
},
|
|
||||||
"aggs": map[string]interface{}{
|
|
||||||
"sumPeople": map[string]interface{}{
|
|
||||||
"sum": map[string]interface{}{
|
|
||||||
"field": "people",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"filtered": map[string]interface{}{
|
"filtered": map[string]interface{}{
|
||||||
"filter": map[string]interface{}{
|
"filter": map[string]interface{}{
|
||||||
"term": map[string]interface{}{
|
"term": map[string]interface{}{
|
||||||
"type": map[string]interface{}{
|
"type": map[string]interface{} {
|
||||||
"value": "t-shirt",
|
"value": "t-shirt",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -115,69 +92,5 @@ func TestAggregations(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"order for termsAggs",
|
|
||||||
//eq.Aggregate(eq.TermsAgg("a1", "FIELD1").Size(0).Aggs(eq.Sum("a2", "FIELD2.SUBFIELD")))
|
|
||||||
Aggregate(
|
|
||||||
TermsAgg("categories", "categories").
|
|
||||||
Order(map[string]string{"priceSum": "desc"}).
|
|
||||||
Size(5).Aggs(Sum("priceSum", "price"))),
|
|
||||||
map[string]interface{}{
|
|
||||||
"aggs": map[string]interface{}{
|
|
||||||
"categories": map[string]interface{}{
|
|
||||||
"terms": map[string]interface{}{
|
|
||||||
"field": "categories",
|
|
||||||
"order": map[string]interface{}{
|
|
||||||
"priceSum": "desc",
|
|
||||||
},
|
|
||||||
"size": 5,
|
|
||||||
},
|
|
||||||
"aggs": map[string]interface{}{
|
|
||||||
"priceSum": map[string]interface{}{
|
|
||||||
"sum": map[string]interface{}{
|
|
||||||
"field": "price",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Single include for termsAggs",
|
|
||||||
//eq.Aggregate(eq.TermsAgg("a1", "FIELD1").Size(0).Aggs(eq.Sum("a2", "FIELD2.SUBFIELD")))
|
|
||||||
Aggregate(
|
|
||||||
TermsAgg("categories", "categories").
|
|
||||||
Include("red.*|blue.*"),
|
|
||||||
),
|
|
||||||
map[string]interface{}{
|
|
||||||
"aggs": map[string]interface{}{
|
|
||||||
"categories": map[string]interface{}{
|
|
||||||
"terms": map[string]interface{}{
|
|
||||||
"field": "categories",
|
|
||||||
"include": "red.*|blue.*",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Multi include for termsAggs",
|
|
||||||
//eq.Aggregate(eq.TermsAgg("a1", "FIELD1").Size(0).Aggs(eq.Sum("a2", "FIELD2.SUBFIELD")))
|
|
||||||
Aggregate(
|
|
||||||
TermsAgg("categories", "categories").
|
|
||||||
Include("red", "blue"),
|
|
||||||
),
|
|
||||||
map[string]interface{}{
|
|
||||||
"aggs": map[string]interface{}{
|
|
||||||
"categories": map[string]interface{}{
|
|
||||||
"terms": map[string]interface{}{
|
|
||||||
"field": "categories",
|
|
||||||
"include": []string{"red", "blue"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
167
aggs_bucket.go
167
aggs_bucket.go
@ -12,8 +12,6 @@ type TermsAggregation struct {
|
|||||||
shardSize *float64
|
shardSize *float64
|
||||||
showTermDoc *bool
|
showTermDoc *bool
|
||||||
aggs []Aggregation
|
aggs []Aggregation
|
||||||
order map[string]string
|
|
||||||
include []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TermsAgg creates a new aggregation of type "terms". The method name includes
|
// TermsAgg creates a new aggregation of type "terms". The method name includes
|
||||||
@ -56,18 +54,6 @@ func (agg *TermsAggregation) Aggs(aggs ...Aggregation) *TermsAggregation {
|
|||||||
return agg
|
return agg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Order sets the sort for terms agg
|
|
||||||
func (agg *TermsAggregation) Order(order map[string]string) *TermsAggregation {
|
|
||||||
agg.order = order
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Include filter the values for buckets
|
|
||||||
func (agg *TermsAggregation) Include(include ...string) *TermsAggregation {
|
|
||||||
agg.include = include
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map returns a map representation of the aggregation, thus implementing the
|
// Map returns a map representation of the aggregation, thus implementing the
|
||||||
// Mappable interface.
|
// Mappable interface.
|
||||||
func (agg *TermsAggregation) Map() map[string]interface{} {
|
func (agg *TermsAggregation) Map() map[string]interface{} {
|
||||||
@ -84,18 +70,6 @@ func (agg *TermsAggregation) Map() map[string]interface{} {
|
|||||||
if agg.showTermDoc != nil {
|
if agg.showTermDoc != nil {
|
||||||
innerMap["show_term_doc_count_error"] = *agg.showTermDoc
|
innerMap["show_term_doc_count_error"] = *agg.showTermDoc
|
||||||
}
|
}
|
||||||
if agg.order != nil {
|
|
||||||
innerMap["order"] = agg.order
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.include != nil {
|
|
||||||
if len(agg.include) <= 1 {
|
|
||||||
innerMap["include"] = agg.include[0]
|
|
||||||
} else {
|
|
||||||
innerMap["include"] = agg.include
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
outerMap := map[string]interface{}{
|
outerMap := map[string]interface{}{
|
||||||
"terms": innerMap,
|
"terms": innerMap,
|
||||||
@ -110,144 +84,3 @@ func (agg *TermsAggregation) Map() map[string]interface{} {
|
|||||||
|
|
||||||
return outerMap
|
return outerMap
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
// DateHistogramAggregation represents an aggregation of type "date_histogram", as described in
|
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/
|
|
||||||
// search-aggregations-bucket-datehistogram-aggregation.html
|
|
||||||
type DateHistogramAggregation struct {
|
|
||||||
name string
|
|
||||||
field string
|
|
||||||
calendarInterval string
|
|
||||||
fixedInterval string
|
|
||||||
format string
|
|
||||||
offset string
|
|
||||||
keyed *bool
|
|
||||||
minDocCount *uint64
|
|
||||||
missing string
|
|
||||||
order map[string]string
|
|
||||||
|
|
||||||
aggs []Aggregation
|
|
||||||
}
|
|
||||||
|
|
||||||
// DateHistogramAgg creates a new aggregation of type "date_histogram".
|
|
||||||
func DateHistogramAgg(name, field string) *DateHistogramAggregation {
|
|
||||||
return &DateHistogramAggregation{
|
|
||||||
name: name,
|
|
||||||
field: field,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the name of the aggregation.
|
|
||||||
func (agg *DateHistogramAggregation) Name() string {
|
|
||||||
return agg.name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aggs sets sub-aggregations for the aggregation.
|
|
||||||
func (agg *DateHistogramAggregation) Aggs(aggs ...Aggregation) *DateHistogramAggregation {
|
|
||||||
agg.aggs = aggs
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// CalendarInterval sets calendarInterval
|
|
||||||
func (agg *DateHistogramAggregation) CalendarInterval(interval string) *DateHistogramAggregation {
|
|
||||||
agg.calendarInterval = interval
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fixedinterval sets fixedInterval
|
|
||||||
func (agg *DateHistogramAggregation) Fixedinterval(interval string) *DateHistogramAggregation {
|
|
||||||
agg.fixedInterval = interval
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format sets format
|
|
||||||
func (agg *DateHistogramAggregation) Format(format string) *DateHistogramAggregation {
|
|
||||||
agg.format = format
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset sets offset
|
|
||||||
func (agg *DateHistogramAggregation) Offset(offset string) *DateHistogramAggregation {
|
|
||||||
agg.offset = offset
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Order sets the sort for terms agg
|
|
||||||
func (agg *DateHistogramAggregation) Order(order map[string]string) *DateHistogramAggregation {
|
|
||||||
agg.order = order
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keyed sets keyed is true or false
|
|
||||||
func (agg *DateHistogramAggregation) Keyed(keyed bool) *DateHistogramAggregation {
|
|
||||||
agg.keyed = &keyed
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Missing sets missing value
|
|
||||||
func (agg *DateHistogramAggregation) Missing(missing string) *DateHistogramAggregation {
|
|
||||||
agg.missing = missing
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// MinDocCount sets min doc count
|
|
||||||
func (agg *DateHistogramAggregation) MinDocCount(minDocCount uint64) *DateHistogramAggregation {
|
|
||||||
agg.minDocCount = &minDocCount
|
|
||||||
return agg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map returns a map representation of the aggregation, thus implementing the
|
|
||||||
// Mappable interface.
|
|
||||||
func (agg *DateHistogramAggregation) Map() map[string]interface{} {
|
|
||||||
innerMap := map[string]interface{}{
|
|
||||||
"field": agg.field,
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.calendarInterval != "" {
|
|
||||||
innerMap["calendar_interval"] = agg.calendarInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.fixedInterval != "" {
|
|
||||||
innerMap["fixed_interval"] = agg.fixedInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.format != "" {
|
|
||||||
innerMap["format"] = agg.format
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.offset != "" {
|
|
||||||
innerMap["offset"] = agg.offset
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.missing != "" {
|
|
||||||
innerMap["missing"] = agg.missing
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.minDocCount != nil {
|
|
||||||
innerMap["min_doc_count"] = agg.minDocCount
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.keyed != nil {
|
|
||||||
innerMap["keyed"] = *agg.keyed
|
|
||||||
}
|
|
||||||
|
|
||||||
if agg.order != nil {
|
|
||||||
innerMap["order"] = agg.order
|
|
||||||
}
|
|
||||||
|
|
||||||
outerMap := map[string]interface{}{
|
|
||||||
"date_histogram": innerMap,
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(agg.aggs) > 0 {
|
|
||||||
subAggs := make(map[string]map[string]interface{})
|
|
||||||
for _, sub := range agg.aggs {
|
|
||||||
subAggs[sub.Name()] = sub.Map()
|
|
||||||
}
|
|
||||||
outerMap["aggs"] = subAggs
|
|
||||||
}
|
|
||||||
|
|
||||||
return outerMap
|
|
||||||
}
|
|
||||||
|
@ -6,7 +6,7 @@ type FilterAggregation struct {
|
|||||||
aggs []Aggregation
|
aggs []Aggregation
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterAgg creates a new aggregation of type "filter". The method name includes
|
// Filter creates a new aggregation of type "filter". The method name includes
|
||||||
// the "Agg" suffix to prevent conflict with the "filter" query.
|
// the "Agg" suffix to prevent conflict with the "filter" query.
|
||||||
func FilterAgg(name string, filter Mappable) *FilterAggregation {
|
func FilterAgg(name string, filter Mappable) *FilterAggregation {
|
||||||
return &FilterAggregation{
|
return &FilterAggregation{
|
||||||
|
@ -44,7 +44,8 @@ func (agg *BaseAgg) Map() map[string]interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AvgAgg represents an aggregation of type "avg", as described in
|
// AvgAgg represents an aggregation of type "avg", as described in
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-avg-aggregation.html
|
// https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-avg-aggregation.html
|
||||||
type AvgAgg struct {
|
type AvgAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
}
|
}
|
||||||
@ -67,7 +68,8 @@ func (agg *AvgAgg) Missing(val interface{}) *AvgAgg {
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// WeightedAvgAgg represents an aggregation of type "weighted_avg", as described
|
// WeightedAvgAgg represents an aggregation of type "weighted_avg", as described
|
||||||
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-weight-avg-aggregation.html
|
// in https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-weight-avg-aggregation.html
|
||||||
type WeightedAvgAgg struct {
|
type WeightedAvgAgg struct {
|
||||||
name string
|
name string
|
||||||
apiName string
|
apiName string
|
||||||
@ -104,7 +106,7 @@ func (agg *WeightedAvgAgg) Value(field string, missing ...interface{}) *Weighted
|
|||||||
return agg
|
return agg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Weight sets the weight field and optionally a value to use when records are
|
// Value sets the weight field and optionally a value to use when records are
|
||||||
// missing a value for the field.
|
// missing a value for the field.
|
||||||
func (agg *WeightedAvgAgg) Weight(field string, missing ...interface{}) *WeightedAvgAgg {
|
func (agg *WeightedAvgAgg) Weight(field string, missing ...interface{}) *WeightedAvgAgg {
|
||||||
agg.Weig = new(BaseAggParams)
|
agg.Weig = new(BaseAggParams)
|
||||||
@ -126,7 +128,8 @@ func (agg *WeightedAvgAgg) Map() map[string]interface{} {
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// CardinalityAgg represents an aggregation of type "cardinality", as described
|
// CardinalityAgg represents an aggregation of type "cardinality", as described
|
||||||
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html
|
// in https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-cardinality-aggregation.html
|
||||||
type CardinalityAgg struct {
|
type CardinalityAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
|
|
||||||
@ -166,7 +169,8 @@ func (agg *CardinalityAgg) Map() map[string]interface{} {
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// MaxAgg represents an aggregation of type "max", as described in:
|
// MaxAgg represents an aggregation of type "max", as described in:
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-max-aggregation.html
|
// https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-max-aggregation.html
|
||||||
type MaxAgg struct {
|
type MaxAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
}
|
}
|
||||||
@ -189,7 +193,8 @@ func (agg *MaxAgg) Missing(val interface{}) *MaxAgg {
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// MinAgg represents an aggregation of type "min", as described in:
|
// MinAgg represents an aggregation of type "min", as described in:
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-min-aggregation.html
|
// https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-min-aggregation.html
|
||||||
type MinAgg struct {
|
type MinAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
}
|
}
|
||||||
@ -212,7 +217,8 @@ func (agg *MinAgg) Missing(val interface{}) *MinAgg {
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// SumAgg represents an aggregation of type "sum", as described in:
|
// SumAgg represents an aggregation of type "sum", as described in:
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-sum-aggregation.html
|
// https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-sum-aggregation.html
|
||||||
type SumAgg struct {
|
type SumAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
}
|
}
|
||||||
@ -235,7 +241,8 @@ func (agg *SumAgg) Missing(val interface{}) *SumAgg {
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// ValueCountAgg represents an aggregation of type "value_count", as described
|
// ValueCountAgg represents an aggregation of type "value_count", as described
|
||||||
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-valuecount-aggregation.html
|
// in https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-valuecount-aggregation.html
|
||||||
type ValueCountAgg struct {
|
type ValueCountAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
}
|
}
|
||||||
@ -251,7 +258,8 @@ func ValueCount(name, field string) *ValueCountAgg {
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// PercentilesAgg represents an aggregation of type "percentiles", as described
|
// PercentilesAgg represents an aggregation of type "percentiles", as described
|
||||||
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-aggregation.html
|
// in https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-percentile-aggregation.html
|
||||||
type PercentilesAgg struct {
|
type PercentilesAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
|
|
||||||
@ -326,7 +334,8 @@ func (agg *PercentilesAgg) Map() map[string]interface{} {
|
|||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
||||||
// StatsAgg represents an aggregation of type "stats", as described in:
|
// StatsAgg represents an aggregation of type "stats", as described in:
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-stats-aggregation.html
|
// https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-stats-aggregation.html
|
||||||
type StatsAgg struct {
|
type StatsAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
}
|
}
|
||||||
@ -348,7 +357,8 @@ func (agg *StatsAgg) Missing(val interface{}) *StatsAgg {
|
|||||||
// ---------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------//
|
||||||
|
|
||||||
// StringStatsAgg represents an aggregation of type "string_stats", as described
|
// StringStatsAgg represents an aggregation of type "string_stats", as described
|
||||||
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-string-stats-aggregation.html
|
// in https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-string-stats-aggregation.html
|
||||||
type StringStatsAgg struct {
|
type StringStatsAgg struct {
|
||||||
*BaseAgg `structs:",flatten"`
|
*BaseAgg `structs:",flatten"`
|
||||||
|
|
||||||
@ -389,7 +399,8 @@ func (agg *StringStatsAgg) Map() map[string]interface{} {
|
|||||||
// ---------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------//
|
||||||
|
|
||||||
// TopHitsAgg represents an aggregation of type "top_hits", as described
|
// TopHitsAgg represents an aggregation of type "top_hits", as described
|
||||||
// in https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-top-hits-aggregation.html
|
// in https://www.elastic.co/guide/en/elasticsearch/reference/
|
||||||
|
// current/search-aggregations-metrics-top-hits-aggregation.html
|
||||||
type TopHitsAgg struct {
|
type TopHitsAgg struct {
|
||||||
name string
|
name string
|
||||||
from uint64
|
from uint64
|
||||||
|
@ -20,7 +20,7 @@ func (agg *NestedAggregation) Name() string {
|
|||||||
return agg.name
|
return agg.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path sets the aggregations path
|
// NumberOfFragments sets the aggregations path
|
||||||
func (agg *NestedAggregation) Path(p string) *NestedAggregation {
|
func (agg *NestedAggregation) Path(p string) *NestedAggregation {
|
||||||
agg.path = p
|
agg.path = p
|
||||||
return agg
|
return agg
|
||||||
|
4
count.go
4
count.go
@ -4,8 +4,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/elastic/go-elasticsearch/v8"
|
"github.com/elastic/go-elasticsearch/v7"
|
||||||
"github.com/elastic/go-elasticsearch/v8/esapi"
|
"github.com/elastic/go-elasticsearch/v7/esapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CountRequest represents a request to get the number of matches for a search
|
// CountRequest represents a request to get the number of matches for a search
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package esquery
|
package esquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/elastic/go-elasticsearch/v8"
|
"github.com/elastic/go-elasticsearch/v7"
|
||||||
"github.com/elastic/go-elasticsearch/v8/esapi"
|
"github.com/elastic/go-elasticsearch/v7/esapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CustomQueryMap represents an arbitrary query map for custom queries.
|
// CustomQueryMap represents an arbitrary query map for custom queries.
|
||||||
@ -21,7 +21,7 @@ func CustomQuery(m map[string]interface{}) *CustomQueryMap {
|
|||||||
// Map returns the custom query as a map[string]interface{}, thus implementing
|
// Map returns the custom query as a map[string]interface{}, thus implementing
|
||||||
// the Mappable interface.
|
// the Mappable interface.
|
||||||
func (m *CustomQueryMap) Map() map[string]interface{} {
|
func (m *CustomQueryMap) Map() map[string]interface{} {
|
||||||
return *m
|
return map[string]interface{}(*m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run executes the custom query using the provided ElasticSearch client. Zero
|
// Run executes the custom query using the provided ElasticSearch client. Zero
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/elastic/go-elasticsearch/v8"
|
"github.com/elastic/go-elasticsearch/v7"
|
||||||
"github.com/elastic/go-elasticsearch/v8/esapi"
|
"github.com/elastic/go-elasticsearch/v7/esapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteRequest represents a request to ElasticSearch's Delete By Query API,
|
// DeleteRequest represents a request to ElasticSearch's Delete By Query API,
|
||||||
|
4
es.go
4
es.go
@ -32,8 +32,8 @@
|
|||||||
// "context"
|
// "context"
|
||||||
// "log"
|
// "log"
|
||||||
//
|
//
|
||||||
// "github.com/aquasecurity/esquery/v8"
|
// "github.com/aquasecurity/esquery"
|
||||||
// "github.com/elastic/go-elasticsearch/v8"
|
// "github.com/elastic/go-elasticsearch/v7"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func main() {
|
// func main() {
|
||||||
|
12
go.mod
12
go.mod
@ -1,14 +1,10 @@
|
|||||||
module git.wilix.dev/golib/esquery
|
module github.com/aquasecurity/esquery
|
||||||
|
|
||||||
go 1.20
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/elastic/go-elasticsearch/v8 v8.10.1
|
github.com/elastic/go-elasticsearch/v7 v7.6.0
|
||||||
github.com/fatih/structs v1.1.0
|
github.com/fatih/structs v1.1.0
|
||||||
|
github.com/jgroeneveld/schema v1.0.0 // indirect
|
||||||
github.com/jgroeneveld/trial v2.0.0+incompatible
|
github.com/jgroeneveld/trial v2.0.0+incompatible
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/elastic/elastic-transport-go/v8 v8.3.0 // indirect
|
|
||||||
github.com/jgroeneveld/schema v1.0.0 // indirect
|
|
||||||
)
|
|
||||||
|
10
go.sum
10
go.sum
@ -1,7 +1,9 @@
|
|||||||
github.com/elastic/elastic-transport-go/v8 v8.3.0 h1:DJGxovyQLXGr62e9nDMPSxRyWION0Bh6d9eCFBriiHo=
|
github.com/elastic/go-elasticsearch v0.0.0 h1:Pd5fqOuBxKxv83b0+xOAJDAkziWYwFinWnBO0y+TZaA=
|
||||||
github.com/elastic/elastic-transport-go/v8 v8.3.0/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI=
|
github.com/elastic/go-elasticsearch v0.0.0/go.mod h1:TkBSJBuTyFdBnrNqoPc54FN0vKf5c04IdM4zuStJ7xg=
|
||||||
github.com/elastic/go-elasticsearch/v8 v8.10.1 h1:JJ3i2DimYTsJcUoEGbg6tNB0eehTNdid9c5kTR1TGuI=
|
github.com/elastic/go-elasticsearch/v7 v7.6.0 h1:sYpGLpEFHgLUKLsZUBfuaVI9QgHjS3JdH9fX4/z8QI8=
|
||||||
github.com/elastic/go-elasticsearch/v8 v8.10.1/go.mod h1:GU1BJHO7WeamP7UhuElYwzzHtvf9SDmeVpSSy9+o6Qg=
|
github.com/elastic/go-elasticsearch/v7 v7.6.0/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
|
||||||
|
github.com/elastic/go-elasticsearch/v8 v8.0.0-20200210103600-aff00e5adfde h1:Y9SZx8RQqFycLxi5W5eFmxMqnmijULVc3LMjBTtZQdM=
|
||||||
|
github.com/elastic/go-elasticsearch/v8 v8.0.0-20200210103600-aff00e5adfde/go.mod h1:xe9a/L2aeOgFKKgrO3ibQTnMdpAeL0GC+5/HpGScSa4=
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/jgroeneveld/schema v1.0.0 h1:J0E10CrOkiSEsw6dfb1IfrDJD14pf6QLVJ3tRPl/syI=
|
github.com/jgroeneveld/schema v1.0.0 h1:J0E10CrOkiSEsw6dfb1IfrDJD14pf6QLVJ3tRPl/syI=
|
||||||
|
10
highlight.go
10
highlight.go
@ -9,7 +9,7 @@ import (
|
|||||||
func (q *QueryHighlight) Map() map[string]interface{} {
|
func (q *QueryHighlight) Map() map[string]interface{} {
|
||||||
results := structs.Map(q.params)
|
results := structs.Map(q.params)
|
||||||
if q.highlightQuery != nil {
|
if q.highlightQuery != nil {
|
||||||
results["highlight_query"] = q.highlightQuery.Map()
|
results["query"] = q.highlightQuery.Map()
|
||||||
}
|
}
|
||||||
if q.fields != nil && len(q.fields) > 0 {
|
if q.fields != nil && len(q.fields) > 0 {
|
||||||
fields := make(map[string]interface{})
|
fields := make(map[string]interface{})
|
||||||
@ -252,9 +252,8 @@ func (a HighlightBoundaryScanner) String() string {
|
|||||||
return "sentence"
|
return "sentence"
|
||||||
case BoundaryScannerWord:
|
case BoundaryScannerWord:
|
||||||
return "word"
|
return "word"
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type HighlightEncoder uint8
|
type HighlightEncoder uint8
|
||||||
@ -282,7 +281,7 @@ func (a HighlightEncoder) String() string {
|
|||||||
type HighlightFragmenter uint8
|
type HighlightFragmenter uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// FragmenterSpan is the "span" value
|
// FragmentSpan is the "span" value
|
||||||
FragmenterSpan HighlightFragmenter = iota
|
FragmenterSpan HighlightFragmenter = iota
|
||||||
|
|
||||||
// FragmenterSimple is the "simple" value
|
// FragmenterSimple is the "simple" value
|
||||||
@ -337,7 +336,6 @@ func (a HighlightTagsSchema) String() string {
|
|||||||
switch a {
|
switch a {
|
||||||
case TagsSchemaStyled:
|
case TagsSchemaStyled:
|
||||||
return "styled"
|
return "styled"
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func (q *BoolQuery) Filter(filter ...Mappable) *BoolQuery {
|
|||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustNot adds one or more queries of type "must_not" to the bool query. MustNot
|
// Must adds one or more queries of type "must_not" to the bool query. MustNot
|
||||||
// can be called multiple times, queries will be appended to existing ones.
|
// can be called multiple times, queries will be appended to existing ones.
|
||||||
func (q *BoolQuery) MustNot(mustnot ...Mappable) *BoolQuery {
|
func (q *BoolQuery) MustNot(mustnot ...Mappable) *BoolQuery {
|
||||||
q.mustNot = append(q.mustNot, mustnot...)
|
q.mustNot = append(q.mustNot, mustnot...)
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
package esquery
|
|
||||||
|
|
||||||
import "github.com/fatih/structs"
|
|
||||||
|
|
||||||
type CombinedFieldsQuery struct {
|
|
||||||
params combinedFieldsParams
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map returns a map representation of the query; implementing the
|
|
||||||
// Mappable interface.
|
|
||||||
func (q *CombinedFieldsQuery) Map() map[string]interface{} {
|
|
||||||
return map[string]interface{}{
|
|
||||||
"combined_fields": structs.Map(q.params),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type combinedFieldsParams struct {
|
|
||||||
Qry interface{} `structs:"query"`
|
|
||||||
Fields []string `structs:"fields"`
|
|
||||||
Boost float32 `structs:"boost,omitempty"`
|
|
||||||
AutoGenerate *bool `structs:"auto_generate_synonyms_phrase_query,omitempty"`
|
|
||||||
Op MatchOperator `structs:"operator,string,omitempty"`
|
|
||||||
MinMatch string `structs:"minimum_should_match,omitempty"`
|
|
||||||
ZeroTerms ZeroTerms `structs:"zero_terms_query,string,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CombinedFields creates a new query of type "combined_fields"
|
|
||||||
func CombinedFields(simpleQuery interface{}) *CombinedFieldsQuery {
|
|
||||||
return newCombinedFields(simpleQuery)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCombinedFields(simpleQuery interface{}) *CombinedFieldsQuery {
|
|
||||||
return &CombinedFieldsQuery{
|
|
||||||
params: combinedFieldsParams{
|
|
||||||
Qry: simpleQuery,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Query sets the data to find in the query's field (it is the "query" component
|
|
||||||
// of the query).
|
|
||||||
func (q *CombinedFieldsQuery) Query(data interface{}) *CombinedFieldsQuery {
|
|
||||||
q.params.Qry = data
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fields sets the fields used in the query
|
|
||||||
func (q *CombinedFieldsQuery) Fields(a ...string) *CombinedFieldsQuery {
|
|
||||||
q.params.Fields = append(q.params.Fields, a...)
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// AutoGenerateSynonymsPhraseQuery sets the "auto_generate_synonyms_phrase_query"
|
|
||||||
// boolean.
|
|
||||||
func (q *CombinedFieldsQuery) AutoGenerateSynonymsPhraseQuery(b bool) *CombinedFieldsQuery {
|
|
||||||
q.params.AutoGenerate = &b
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// Boost sets the query boost
|
|
||||||
func (q *CombinedFieldsQuery) Boost(l float32) *CombinedFieldsQuery {
|
|
||||||
q.params.Boost = l
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operator sets the boolean logic used to interpret text in the query value.
|
|
||||||
func (q *CombinedFieldsQuery) Operator(op MatchOperator) *CombinedFieldsQuery {
|
|
||||||
q.params.Op = op
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// MinimumShouldMatch sets the minimum number of clauses that must match for a
|
|
||||||
// document to be returned.
|
|
||||||
func (q *CombinedFieldsQuery) MinimumShouldMatch(s string) *CombinedFieldsQuery {
|
|
||||||
q.params.MinMatch = s
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZeroTermsQuery sets the "zero_terms_query" option to use. This indicates
|
|
||||||
// whether no documents are returned if the analyzer removes all tokens, such as
|
|
||||||
// when using a stop filter.
|
|
||||||
func (q *CombinedFieldsQuery) ZeroTermsQuery(s ZeroTerms) *CombinedFieldsQuery {
|
|
||||||
q.params.ZeroTerms = s
|
|
||||||
return q
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package esquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCombinedFields(t *testing.T) {
|
|
||||||
runMapTests(t, []mapTest{
|
|
||||||
{
|
|
||||||
"simple combined_fields",
|
|
||||||
CombinedFields("value1").Fields("title"),
|
|
||||||
map[string]interface{}{
|
|
||||||
"combined_fields": map[string]interface{}{
|
|
||||||
"fields": []string{"title"},
|
|
||||||
"query": "value1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"combined_fields all params",
|
|
||||||
CombinedFields("original").
|
|
||||||
Query("test").
|
|
||||||
Fields("title", "body").
|
|
||||||
AutoGenerateSynonymsPhraseQuery(true).
|
|
||||||
Boost(6.4).
|
|
||||||
Operator(OperatorAnd).
|
|
||||||
MinimumShouldMatch("3<90%").
|
|
||||||
ZeroTermsQuery(ZeroTermsAll),
|
|
||||||
map[string]interface{}{
|
|
||||||
"combined_fields": map[string]interface{}{
|
|
||||||
"auto_generate_synonyms_phrase_query": true,
|
|
||||||
"boost": 6.4,
|
|
||||||
"minimum_should_match": "3<90%",
|
|
||||||
"operator": "AND",
|
|
||||||
"zero_terms_query": "all",
|
|
||||||
"query": "test",
|
|
||||||
"fields": []string{"title", "body"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
package esquery
|
|
||||||
|
|
||||||
// NestedQuery represents a query of type nested as described in:
|
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html
|
|
||||||
type NestedQuery struct {
|
|
||||||
path string
|
|
||||||
query Mappable
|
|
||||||
scoreMode string
|
|
||||||
ignoreUnmapped bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func Nested(path string, query Mappable) *NestedQuery {
|
|
||||||
return &NestedQuery{
|
|
||||||
path: path,
|
|
||||||
query: query,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NestedQuery) ScoreMode(mode string) *NestedQuery {
|
|
||||||
n.scoreMode = mode
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *NestedQuery) IgnoreUnmapped(val bool) *NestedQuery {
|
|
||||||
n.ignoreUnmapped = val
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map returns a map representation of the query, thus implementing the
|
|
||||||
// Mappable interface.
|
|
||||||
func (n *NestedQuery) Map() map[string]interface{} {
|
|
||||||
innerMap := map[string]interface{}{"path": n.path, "query": n.query.Map()}
|
|
||||||
if n.scoreMode != "" {
|
|
||||||
innerMap["score_mode"] = n.scoreMode
|
|
||||||
}
|
|
||||||
if n.ignoreUnmapped == true {
|
|
||||||
innerMap["ignore_unmapped"] = n.ignoreUnmapped
|
|
||||||
}
|
|
||||||
return map[string]interface{}{"nested": innerMap}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package esquery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNested(t *testing.T) {
|
|
||||||
runMapTests(t, []mapTest{
|
|
||||||
{
|
|
||||||
"Nested Query",
|
|
||||||
Nested("dns_values", Term("dns_values.type", "A")).ScoreMode("max").IgnoreUnmapped(true),
|
|
||||||
map[string]interface{}{
|
|
||||||
"nested": map[string]interface{}{
|
|
||||||
"path": "dns_values",
|
|
||||||
"query": Term("dns_values.type", "A").Map(),
|
|
||||||
"score_mode": "max",
|
|
||||||
"ignore_unmapped": true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
@ -10,7 +10,7 @@ const (
|
|||||||
// TypeMatch denotes a query of type "match"
|
// TypeMatch denotes a query of type "match"
|
||||||
TypeMatch matchType = iota
|
TypeMatch matchType = iota
|
||||||
|
|
||||||
// TypeMatchBoolPrefix denotes a query of type "match_bool_prefix"
|
// TypeMatchBool denotes a query of type "match_bool_prefix"
|
||||||
TypeMatchBoolPrefix
|
TypeMatchBoolPrefix
|
||||||
|
|
||||||
// TypeMatchPhrase denotes a query of type "match_phrase"
|
// TypeMatchPhrase denotes a query of type "match_phrase"
|
||||||
@ -71,7 +71,6 @@ type matchParams struct {
|
|||||||
MinMatch string `structs:"minimum_should_match,omitempty"`
|
MinMatch string `structs:"minimum_should_match,omitempty"`
|
||||||
ZeroTerms ZeroTerms `structs:"zero_terms_query,string,omitempty"`
|
ZeroTerms ZeroTerms `structs:"zero_terms_query,string,omitempty"`
|
||||||
Slp uint16 `structs:"slop,omitempty"` // only relevant for match_phrase query
|
Slp uint16 `structs:"slop,omitempty"` // only relevant for match_phrase query
|
||||||
Boost float32 `structs:"boost,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match creates a new query of type "match" with the provided field name.
|
// Match creates a new query of type "match" with the provided field name.
|
||||||
@ -203,12 +202,6 @@ func (q *MatchQuery) ZeroTermsQuery(s ZeroTerms) *MatchQuery {
|
|||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boost sets the boost value of the query.
|
|
||||||
func (q *MatchQuery) Boost(b float32) *MatchQuery {
|
|
||||||
q.params.Boost = b
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchOperator is an enumeration type representing supported values for a
|
// MatchOperator is an enumeration type representing supported values for a
|
||||||
// match query's "operator" parameter.
|
// match query's "operator" parameter.
|
||||||
type MatchOperator uint8
|
type MatchOperator uint8
|
||||||
|
@ -17,18 +17,6 @@ func TestMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"simple match",
|
|
||||||
Match("title", "sample text").Boost(50),
|
|
||||||
map[string]interface{}{
|
|
||||||
"match": map[string]interface{}{
|
|
||||||
"title": map[string]interface{}{
|
|
||||||
"query": "sample text",
|
|
||||||
"boost": 50,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"match with more params",
|
"match with more params",
|
||||||
Match("issue_number").Query(16).Transpositions(false).MaxExpansions(32).Operator(OperatorAnd),
|
Match("issue_number").Query(16).Transpositions(false).MaxExpansions(32).Operator(OperatorAnd),
|
||||||
|
@ -18,7 +18,7 @@ func (q *MultiMatchQuery) Map() map[string]interface{} {
|
|||||||
|
|
||||||
type multiMatchParams struct {
|
type multiMatchParams struct {
|
||||||
Qry interface{} `structs:"query"`
|
Qry interface{} `structs:"query"`
|
||||||
Fields []string `structs:"fields,omitempty"`
|
Fields []string `structs:"fields"`
|
||||||
Type MultiMatchType `structs:"type,string,omitempty"`
|
Type MultiMatchType `structs:"type,string,omitempty"`
|
||||||
TieBrk float32 `structs:"tie_breaker,omitempty"`
|
TieBrk float32 `structs:"tie_breaker,omitempty"`
|
||||||
Boost float32 `structs:"boost,omitempty"`
|
Boost float32 `structs:"boost,omitempty"`
|
||||||
@ -100,13 +100,13 @@ func (q *MultiMatchQuery) PrefixLength(l uint16) *MultiMatchQuery {
|
|||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
// TieBreaker sets the query tiebreaker
|
// TieBreaker
|
||||||
func (q *MultiMatchQuery) TieBreaker(l float32) *MultiMatchQuery {
|
func (q *MultiMatchQuery) TieBreaker(l float32) *MultiMatchQuery {
|
||||||
q.params.TieBrk = l
|
q.params.TieBrk = l
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
// Boost sets the query boost
|
// Boost
|
||||||
func (q *MultiMatchQuery) Boost(l float32) *MultiMatchQuery {
|
func (q *MultiMatchQuery) Boost(l float32) *MultiMatchQuery {
|
||||||
q.params.Boost = l
|
q.params.Boost = l
|
||||||
return q
|
return q
|
||||||
@ -164,27 +164,27 @@ func (q *MultiMatchQuery) ZeroTermsQuery(s ZeroTerms) *MultiMatchQuery {
|
|||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultiMatchType is an enumeration type representing supported values for a
|
// MatchType is an enumeration type representing supported values for a
|
||||||
// multi match query's "type" parameter.
|
// multi match query's "type" parameter.
|
||||||
type MultiMatchType uint8
|
type MultiMatchType uint8
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// MatchTypeBestFields is the "best_fields" type
|
// TypeBestFields is the "best_fields" type
|
||||||
MatchTypeBestFields MultiMatchType = iota
|
MatchTypeBestFields MultiMatchType = iota
|
||||||
|
|
||||||
// MatchTypeMostFields is the "most_fields" type
|
// TypeMostFields is the "most_fields" type
|
||||||
MatchTypeMostFields
|
MatchTypeMostFields
|
||||||
|
|
||||||
// MatchTypeCrossFields is the "cross_fields" type
|
// TypeMostFields is the "cross_fields" type
|
||||||
MatchTypeCrossFields
|
MatchTypeCrossFields
|
||||||
|
|
||||||
// MatchTypePhrase is the "phrase" type
|
// TypeMostFields is the "phrase" type
|
||||||
MatchTypePhrase
|
MatchTypePhrase
|
||||||
|
|
||||||
// MatchTypePhrasePrefix is the "phrase_prefix" type
|
// TypeMostFields is the "phrase_prefix" type
|
||||||
MatchTypePhrasePrefix
|
MatchTypePhrasePrefix
|
||||||
|
|
||||||
// MatchTypeBoolPrefix is the "bool_prefix" type
|
// TypeMostFields is the "bool_prefix" type
|
||||||
MatchTypeBoolPrefix
|
MatchTypeBoolPrefix
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ func (a *RangeQuery) Gt(val interface{}) *RangeQuery {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gte sets that the value of field must be greater than or equal to the provided
|
// Gt sets that the value of field must be greater than or equal to the provided
|
||||||
// value
|
// value
|
||||||
func (a *RangeQuery) Gte(val interface{}) *RangeQuery {
|
func (a *RangeQuery) Gte(val interface{}) *RangeQuery {
|
||||||
a.params.Gte = val
|
a.params.Gte = val
|
||||||
@ -454,7 +454,7 @@ func (q *TermsQuery) Boost(b float32) *TermsQuery {
|
|||||||
|
|
||||||
// Map returns a map representation of the query, thus implementing the
|
// Map returns a map representation of the query, thus implementing the
|
||||||
// Mappable interface.
|
// Mappable interface.
|
||||||
func (q *TermsQuery) Map() map[string]interface{} {
|
func (q TermsQuery) Map() map[string]interface{} {
|
||||||
innerMap := map[string]interface{}{q.field: q.values}
|
innerMap := map[string]interface{}{q.field: q.values}
|
||||||
if q.boost > 0 {
|
if q.boost > 0 {
|
||||||
innerMap["boost"] = q.boost
|
innerMap["boost"] = q.boost
|
||||||
@ -511,52 +511,10 @@ func (q *TermsSetQuery) MinimumShouldMatchScript(script string) *TermsSetQuery {
|
|||||||
|
|
||||||
// Map returns a map representation of the query, thus implementing the
|
// Map returns a map representation of the query, thus implementing the
|
||||||
// Mappable interface.
|
// Mappable interface.
|
||||||
func (q *TermsSetQuery) Map() map[string]interface{} {
|
func (q TermsSetQuery) Map() map[string]interface{} {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"terms_set": map[string]interface{}{
|
"terms_set": map[string]interface{}{
|
||||||
q.field: structs.Map(q.params),
|
q.field: structs.Map(q.params),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GeoFilter geoFilterParams represents a query of type "geo_distance", as described in:
|
|
||||||
// https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-geo-distance-query.html
|
|
||||||
type GeoFilter struct {
|
|
||||||
params geoFilterParams
|
|
||||||
filed string
|
|
||||||
}
|
|
||||||
|
|
||||||
func GeoFilterFunc(distance string, MiddleCentroid []float64, filed string) *GeoFilter {
|
|
||||||
return &GeoFilter{
|
|
||||||
params: geoFilterParams{
|
|
||||||
Distance: distance,
|
|
||||||
MiddleCentroid: MiddleCentroid,
|
|
||||||
},
|
|
||||||
filed: filed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type geoFilterParams struct {
|
|
||||||
Distance string `structs:"distance,omitempty"`
|
|
||||||
MiddleCentroid []float64 `structs:"location,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GeoFilter) Distance(distance string) *GeoFilter {
|
|
||||||
g.params.Distance = distance
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
func (g *GeoFilter) MiddleCentroid(middleCentroid []float64) *GeoFilter {
|
|
||||||
g.params.MiddleCentroid = middleCentroid
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GeoFilter) Map() map[string]interface{} {
|
|
||||||
m := structs.Map(g.params)
|
|
||||||
m[g.filed] = m["location"]
|
|
||||||
delete(m, "location")
|
|
||||||
response := map[string]interface{}{
|
|
||||||
"geo_distance": m}
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
}
|
|
||||||
|
48
search.go
48
search.go
@ -4,10 +4,10 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/elastic/go-elasticsearch/v8"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/elastic/go-elasticsearch/v8/esapi"
|
"github.com/elastic/go-elasticsearch/v7"
|
||||||
|
"github.com/elastic/go-elasticsearch/v7/esapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SearchRequest represents a request to ElasticSearch's Search API, described
|
// SearchRequest represents a request to ElasticSearch's Search API, described
|
||||||
@ -15,18 +15,16 @@ import (
|
|||||||
// Not all features of the search API are currently supported, but a request can
|
// Not all features of the search API are currently supported, but a request can
|
||||||
// currently include a query, aggregations, and more.
|
// currently include a query, aggregations, and more.
|
||||||
type SearchRequest struct {
|
type SearchRequest struct {
|
||||||
aggs []Aggregation
|
aggs []Aggregation
|
||||||
explain *bool
|
explain *bool
|
||||||
from *uint64
|
from *uint64
|
||||||
highlight Mappable
|
highlight Mappable
|
||||||
searchAfter []interface{}
|
postFilter Mappable
|
||||||
postFilter Mappable
|
query Mappable
|
||||||
query Mappable
|
size *uint64
|
||||||
size *uint64
|
sort Sort
|
||||||
sort Sort
|
source Source
|
||||||
source Source
|
timeout *time.Duration
|
||||||
collapse map[string]interface{}
|
|
||||||
timeout *time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search creates a new SearchRequest object, to be filled via method chaining.
|
// Search creates a new SearchRequest object, to be filled via method chaining.
|
||||||
@ -40,14 +38,6 @@ func (req *SearchRequest) Query(q Mappable) *SearchRequest {
|
|||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collapse sets one field to collapse for the request.
|
|
||||||
func (req *SearchRequest) Collapse(field string) *SearchRequest {
|
|
||||||
req.collapse = map[string]interface{}{
|
|
||||||
"field": field,
|
|
||||||
}
|
|
||||||
return req
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aggs sets one or more aggregations for the request.
|
// Aggs sets one or more aggregations for the request.
|
||||||
func (req *SearchRequest) Aggs(aggs ...Aggregation) *SearchRequest {
|
func (req *SearchRequest) Aggs(aggs ...Aggregation) *SearchRequest {
|
||||||
req.aggs = append(req.aggs, aggs...)
|
req.aggs = append(req.aggs, aggs...)
|
||||||
@ -84,12 +74,6 @@ func (req *SearchRequest) Sort(name string, order Order) *SearchRequest {
|
|||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchAfter retrieve the sorted result
|
|
||||||
func (req *SearchRequest) SearchAfter(s ...interface{}) *SearchRequest {
|
|
||||||
req.searchAfter = append(req.searchAfter, s...)
|
|
||||||
return req
|
|
||||||
}
|
|
||||||
|
|
||||||
// Explain sets whether the ElasticSearch API should return an explanation for
|
// Explain sets whether the ElasticSearch API should return an explanation for
|
||||||
// how each hit's score was calculated.
|
// how each hit's score was calculated.
|
||||||
func (req *SearchRequest) Explain(b bool) *SearchRequest {
|
func (req *SearchRequest) Explain(b bool) *SearchRequest {
|
||||||
@ -121,6 +105,7 @@ func (req *SearchRequest) Highlight(highlight Mappable) *SearchRequest {
|
|||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Map implements the Mappable interface. It converts the request to into a
|
// Map implements the Mappable interface. It converts the request to into a
|
||||||
// nested map[string]interface{}, as expected by the go-elasticsearch library.
|
// nested map[string]interface{}, as expected by the go-elasticsearch library.
|
||||||
func (req *SearchRequest) Map() map[string]interface{} {
|
func (req *SearchRequest) Map() map[string]interface{} {
|
||||||
@ -157,13 +142,6 @@ func (req *SearchRequest) Map() map[string]interface{} {
|
|||||||
if req.highlight != nil {
|
if req.highlight != nil {
|
||||||
m["highlight"] = req.highlight.Map()
|
m["highlight"] = req.highlight.Map()
|
||||||
}
|
}
|
||||||
if req.searchAfter != nil {
|
|
||||||
m["search_after"] = req.searchAfter
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.collapse != nil {
|
|
||||||
m["collapse"] = req.collapse
|
|
||||||
}
|
|
||||||
|
|
||||||
source := req.source.Map()
|
source := req.source.Map()
|
||||||
if len(source) > 0 {
|
if len(source) > 0 {
|
||||||
|
@ -7,13 +7,6 @@ import (
|
|||||||
|
|
||||||
func TestSearchMaps(t *testing.T) {
|
func TestSearchMaps(t *testing.T) {
|
||||||
runMapTests(t, []mapTest{
|
runMapTests(t, []mapTest{
|
||||||
{
|
|
||||||
"a simple query with search after",
|
|
||||||
Search().SearchAfter("_id", "name"),
|
|
||||||
map[string]interface{}{
|
|
||||||
"search_after": []string{"_id", "name"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"a simple match_all query with a size and no aggs",
|
"a simple match_all query with a size and no aggs",
|
||||||
Search().Query(MatchAll()).Size(20),
|
Search().Query(MatchAll()).Size(20),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user