Merge pull request 'search-collapse' (#6) from search-collapse into master

Reviewed-on: #6
This commit is contained in:
Maxim Yanchuk 2023-11-01 21:11:51 +00:00
commit 313fe61951
4 changed files with 75 additions and 4 deletions

2
go.mod
View File

@ -1,4 +1,4 @@
module github.com/aquasecurity/esquery module github.com/okdanta/esquery
go 1.13 go 1.13

40
query_joining.go Normal file
View File

@ -0,0 +1,40 @@
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}
}

22
query_joining_test.go Normal file
View File

@ -0,0 +1,22 @@
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,
},
},
},
})
}

View File

@ -25,8 +25,8 @@ type SearchRequest struct {
size *uint64 size *uint64
sort Sort sort Sort
source Source source Source
collapse map[string]interface{}
timeout *time.Duration 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,6 +40,14 @@ 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...)
@ -113,8 +121,6 @@ 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{} {
@ -155,6 +161,9 @@ func (req *SearchRequest) Map() map[string]interface{} {
m["search_after"] = req.searchAfter 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 {