2022-07-06 23:19:05 +02:00
|
|
|
package search
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2023-01-07 22:25:56 +02:00
|
|
|
const randomSortKey string = "@random"
|
|
|
|
|
2022-07-06 23:19:05 +02:00
|
|
|
// sort field directions
|
|
|
|
const (
|
|
|
|
SortAsc string = "ASC"
|
|
|
|
SortDesc string = "DESC"
|
|
|
|
)
|
|
|
|
|
|
|
|
// SortField defines a single search sort field.
|
|
|
|
type SortField struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Direction string `json:"direction"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// BuildExpr resolves the sort field into a valid db sort expression.
|
|
|
|
func (s *SortField) BuildExpr(fieldResolver FieldResolver) (string, error) {
|
2023-01-07 22:25:56 +02:00
|
|
|
// special case for random sort
|
|
|
|
if s.Name == randomSortKey {
|
|
|
|
return "RANDOM()", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
result, err := fieldResolver.Resolve(s.Name)
|
2022-07-06 23:19:05 +02:00
|
|
|
|
|
|
|
// invalidate empty fields and non-column identifiers
|
2023-01-07 22:25:56 +02:00
|
|
|
if err != nil || len(result.Params) > 0 || result.Identifier == "" || strings.ToLower(result.Identifier) == "null" {
|
|
|
|
return "", fmt.Errorf("invalid sort field %q", s.Name)
|
2022-07-06 23:19:05 +02:00
|
|
|
}
|
|
|
|
|
2023-01-07 22:25:56 +02:00
|
|
|
return fmt.Sprintf("%s %s", result.Identifier, s.Direction), nil
|
2022-07-06 23:19:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ParseSortFromString parses the provided string expression
|
|
|
|
// into a slice of SortFields.
|
|
|
|
//
|
|
|
|
// Example:
|
2023-02-23 21:51:42 +02:00
|
|
|
//
|
2022-07-06 23:19:05 +02:00
|
|
|
// fields := search.ParseSortFromString("-name,+created")
|
2022-07-12 18:52:09 +02:00
|
|
|
func ParseSortFromString(str string) (fields []SortField) {
|
2022-07-06 23:19:05 +02:00
|
|
|
data := strings.Split(str, ",")
|
|
|
|
|
|
|
|
for _, field := range data {
|
|
|
|
// trim whitespaces
|
|
|
|
field = strings.TrimSpace(field)
|
|
|
|
if strings.HasPrefix(field, "-") {
|
2022-07-12 18:52:09 +02:00
|
|
|
fields = append(fields, SortField{strings.TrimPrefix(field, "-"), SortDesc})
|
2022-07-06 23:19:05 +02:00
|
|
|
} else {
|
2022-07-12 18:52:09 +02:00
|
|
|
fields = append(fields, SortField{strings.TrimPrefix(field, "+"), SortAsc})
|
2022-07-06 23:19:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-12 18:52:09 +02:00
|
|
|
return
|
2022-07-06 23:19:05 +02:00
|
|
|
}
|