Skip to content

Commit 0b226a6

Browse files
authored
Merge pull request #11 from harshit98/sort-clause-support
feat: extend support for sort clauses
2 parents 367e27a + d03f362 commit 0b226a6

File tree

5 files changed

+416
-28
lines changed

5 files changed

+416
-28
lines changed

common.go

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,3 @@ func (source Source) Map() map[string]interface{} {
2222
}
2323
return m
2424
}
25-
26-
// Sort represents a list of keys to sort by.
27-
type Sort []map[string]interface{}
28-
29-
// Order is the ordering for a sort key (ascending, descending).
30-
type Order string
31-
32-
const (
33-
// OrderAsc represents sorting in ascending order.
34-
OrderAsc Order = "asc"
35-
36-
// OrderDesc represents sorting in descending order.
37-
OrderDesc Order = "desc"
38-
)

search.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77
"fmt"
88
"time"
99

10-
opensearch "github.com/opensearch-project/opensearch-go/v4"
11-
opensearchapi "github.com/opensearch-project/opensearch-go/v4/opensearchapi"
10+
"github.com/opensearch-project/opensearch-go/v4"
11+
"github.com/opensearch-project/opensearch-go/v4/opensearchapi"
1212
)
1313

1414
// SearchRequest represents the parameters for an OpenSearch query.
@@ -21,7 +21,7 @@ type SearchRequest struct {
2121
postFilter Mappable
2222
query Mappable
2323
size *uint64
24-
sort Sort
24+
sort []SortOption
2525
source Source
2626
timeout *time.Duration
2727
scriptFields []*ScriptField
@@ -63,14 +63,12 @@ func (req *SearchRequest) Size(size uint64) *SearchRequest {
6363
return req
6464
}
6565

66-
// Sort sets how the results should be sorted.
67-
func (req *SearchRequest) Sort(name string, order Order) *SearchRequest {
68-
req.sort = append(req.sort, map[string]interface{}{
69-
name: map[string]interface{}{
70-
"order": order,
71-
},
72-
})
73-
66+
// Sort appends one or more sort options.
67+
// Accepts any type that implements SortOption (field, script, raw)
68+
func (req *SearchRequest) Sort(opts ...SortOption) *SearchRequest {
69+
if opts != nil {
70+
req.sort = append(req.sort, opts...)
71+
}
7472
return req
7573
}
7674

@@ -136,7 +134,11 @@ func (req *SearchRequest) Map() map[string]interface{} {
136134
m["size"] = *req.size
137135
}
138136
if len(req.sort) > 0 {
139-
m["sort"] = req.sort
137+
sortSlice := make([]any, 0, len(req.sort))
138+
for _, params := range req.sort {
139+
sortSlice = append(sortSlice, params.Map())
140+
}
141+
m["sort"] = sortSlice
140142
}
141143
if req.from != nil {
142144
m["from"] = *req.from

search_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ func TestSearchMaps(t *testing.T) {
5757
Size(30).
5858
From(5).
5959
Explain(true).
60-
Sort("field_1", OrderDesc).
61-
Sort("field_2", OrderAsc).
60+
Sort(
61+
FieldSort("field_1").Order(OrderDesc),
62+
FieldSort("field_2").Order(OrderAsc),
63+
).
6264
SourceIncludes("field_1", "field_2").
6365
SourceExcludes("field_3").
6466
Timeout(time.Duration(20000000000)).

sort.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package osquery
2+
3+
// Order is the ordering for a sort key (ascending, descending).
4+
type Order string
5+
6+
const (
7+
// OrderAsc represents sorting in ascending order.
8+
OrderAsc Order = "asc"
9+
10+
// OrderDesc represents sorting in descending order.
11+
OrderDesc Order = "desc"
12+
)
13+
14+
// Mode is the mode for a sort key (min, max, sum, avg, median).
15+
type Mode string
16+
17+
const (
18+
// SortModeMin represents the minimum value.
19+
SortModeMin Mode = "min"
20+
21+
// SortModeMax represents the maximum value.
22+
SortModeMax Mode = "max"
23+
24+
// SortModeSum represents the sum of values.
25+
SortModeSum Mode = "sum"
26+
27+
// SortModeAvg represents the average of values.
28+
SortModeAvg Mode = "avg"
29+
30+
// SortModeMedian represents the median of values.
31+
SortModeMedian Mode = "median"
32+
)
33+
34+
// SortOption is an interface for different types of sort options
35+
type SortOption interface {
36+
Map() map[string]any
37+
}
38+
39+
// ScriptSortOption represents a script-based sort option for elasticsearch
40+
type ScriptSortOption struct {
41+
sortType string
42+
script *ScriptField
43+
order Order
44+
}
45+
46+
// ScriptSort creates a new query of type "_script" with the provided
47+
// type and script.
48+
func ScriptSort(scriptField *ScriptField, sortType string) *ScriptSortOption {
49+
return &ScriptSortOption{
50+
script: scriptField,
51+
sortType: sortType,
52+
}
53+
}
54+
55+
func (s *ScriptSortOption) Order(order Order) *ScriptSortOption {
56+
s.order = order
57+
return s
58+
}
59+
60+
func (s *ScriptSortOption) Map() map[string]any {
61+
scriptMapRaw, ok := s.script.Map()["script"]
62+
if !ok {
63+
return nil
64+
}
65+
66+
scriptMap, ok := scriptMapRaw.(map[string]any)
67+
if !ok {
68+
return nil
69+
}
70+
71+
sortOptions := map[string]any{
72+
"type": s.sortType,
73+
"script": scriptMap,
74+
}
75+
76+
if s.order != "" {
77+
sortOptions["order"] = s.order
78+
}
79+
80+
return map[string]any{
81+
"_script": sortOptions,
82+
}
83+
}
84+
85+
type FieldSortOption struct {
86+
field string
87+
order Order
88+
mode Mode
89+
nestedPath string
90+
nestedFilter Mappable
91+
}
92+
93+
func FieldSort(field string) *FieldSortOption {
94+
return &FieldSortOption{
95+
field: field,
96+
}
97+
}
98+
99+
func (f *FieldSortOption) Order(order Order) *FieldSortOption {
100+
f.order = order
101+
return f
102+
}
103+
104+
func (f *FieldSortOption) Mode(mode Mode) *FieldSortOption {
105+
f.mode = mode
106+
return f
107+
}
108+
109+
func (f *FieldSortOption) NestedPath(nestedPath string) *FieldSortOption {
110+
f.nestedPath = nestedPath
111+
return f
112+
}
113+
114+
func (f *FieldSortOption) NestedFilter(nestedFilter Mappable) *FieldSortOption {
115+
f.nestedFilter = nestedFilter
116+
return f
117+
}
118+
119+
func (f *FieldSortOption) Map() map[string]any {
120+
sortOptions := map[string]any{}
121+
122+
if f.order != "" {
123+
sortOptions["order"] = f.order
124+
}
125+
126+
if f.mode != "" {
127+
sortOptions["mode"] = f.mode
128+
}
129+
130+
if f.nestedPath != "" {
131+
sortOptions["nested_path"] = f.nestedPath
132+
133+
if f.nestedFilter != nil {
134+
sortOptions["nested_filter"] = f.nestedFilter.Map()
135+
}
136+
}
137+
138+
return map[string]any{
139+
f.field: sortOptions,
140+
}
141+
}

0 commit comments

Comments
 (0)