feat(search): native order_by sorting in the opensearch backend

Name is analyzed (lowercaseKeyword) and therefore a text field, which
OpenSearch refuses to sort on without fielddata; enable it in the index
template. The keyword tokenizer emits one term per document, so the
fielddata cache stays small. The schema version has not shipped yet, so
no reindex is needed.

(cherry picked from commit f1d0e7b773b170b119dbd59fa176d656237bed96)
This commit is contained in:
Dominik Schmidt committed 2026-09-08 00:26:03 +02:00
1 parent 55b89d02d4
commit 79e616da3a
3 files changed
+22 -1

No files matched your search

+21
View File
@@ -127,6 +127,26 @@ func (b *Backend) Search(ctx context.Context, sir *searchService.SearchIndexRequ
if err != nil {
return nil, err
}
// Sort natively in the index; the service layer re-establishes this order
// when merging matches across spaces. Score sorting (the default) stays in
// place when no order_by is given. Missing values sort last in both
// directions, matching the cross-space merge.
var sortClause []map[string]any
if orderBy := sir.GetOrderBy(); len(orderBy) > 0 {
sortClause = make([]map[string]any, 0, len(orderBy)+1)
for _, sp := range orderBy {
field, ok := search.SortIndexField(sp.GetName())
if !ok {
return nil, errtypes.BadRequest(fmt.Sprintf("field %q is not sortable", sp.GetName()))
}
order := "asc"
if sp.GetIsDescending() {
order = "desc"
}
sortClause = append(sortClause, map[string]any{field: map[string]any{"order": order, "missing": "_last"}})
}
sortClause = append(sortClause, map[string]any{"_score": map[string]any{"order": "desc"}})
}
req, err := osu.BuildSearchReq(&opensearchgoAPI.SearchReq{
Indices: []string{b.index},
@@ -147,6 +167,7 @@ func (b *Backend) Search(ctx context.Context, sir *searchService.SearchIndexRequ
},
},
Aggs: builtAggs,
Sort: sortClause,
},
)
if err != nil {
-1
View File
@@ -74,7 +74,6 @@ func buildResourceMapping() ([]byte, error) {
if err != nil {
return nil, err
}
index := map[string]any{
"settings": map[string]any{
"number_of_shards": "1",
@@ -96,6 +96,7 @@ func BuildSearchReq(req *opensearchgoAPI.SearchReq, q Builder, p ...SearchBodyPa
type SearchBodyParams struct {
Highlight *BodyParamHighlight `json:"highlight,omitempty"`
Aggs map[string]any `json:"aggs,omitempty"`
Sort []map[string]any `json:"sort,omitempty"`
}
//----------------------------------------------------------------------------//