Skip to content

Commit

Permalink
handle sort elasticsearch
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyenhuuhien22072001 committed Sep 24, 2023
1 parent e7151d4 commit 12c731f
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 11 deletions.
20 changes: 18 additions & 2 deletions elasticsearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ func FindAndDecode(ctx context.Context, es *elasticsearch.Client, indexName []st
return false, err
}
defer res.Body.Close()


modelType := reflect.TypeOf(result).Elem().Elem()
if res.IsError() {
return false, errors.New("response error")
} else {
Expand All @@ -255,7 +256,22 @@ func FindAndDecode(ctx context.Context, es *elasticsearch.Client, indexName []st
return false, err
} else {
hits := r["hits"].(map[string]interface{})["hits"].([]interface{})
if err := json.NewDecoder(esutil.NewJSONReader(hits)).Decode(&result); err != nil {
listResults := make([]interface{}, 0)
for _, hit := range hits {
r := hit.(map[string]interface{})["_source"]
r.(map[string]interface{})["id"] = hit.(map[string]interface{})["_id"]
stValue := reflect.New(modelType).Elem()
for i := 0; i < modelType.NumField(); i++ {
field := modelType.Field(i)
if value, ok := r.(map[string]interface{})[field.Name]; ok {
stValue.Field(i).Set(reflect.ValueOf(value))
}
}
listResults = append(listResults, r)
}

err := json.NewDecoder(esutil.NewJSONReader(listResults)).Decode(result)
if err != nil {
return false, err
}
return true, nil
Expand Down
59 changes: 51 additions & 8 deletions query.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"strings"
)

func BuildSearchResult(ctx context.Context, db *elasticsearch.Client, results interface{}, indexName string, query map[string]interface{}, sort []string, limit int64, offset int64, modelType reflect.Type, options ...func(context.Context, interface{}) (interface{}, error)) (int64, error) {
func BuildSearchResult(ctx context.Context, db *elasticsearch.Client, results interface{}, indexName string, query map[string]interface{}, sort []map[string]interface{}, limit int64, offset int64, modelType reflect.Type, options ...func(context.Context, interface{}) (interface{}, error)) (int64, error) {
var mp func(context.Context, interface{}) (interface{}, error)
if len(options) > 0 {
mp = options[0]
Expand All @@ -20,10 +20,10 @@ func BuildSearchResult(ctx context.Context, db *elasticsearch.Client, results in
from := int(offset)
size := int(limit)
fullQuery := UpdateQuery(query)
fullQuery["sort"] = sort
req := esapi.SearchRequest{
Index: []string{indexName},
Body: esutil.NewJSONReader(fullQuery),
Sort: sort,
From: &from,
Size: &size,
}
Expand All @@ -44,9 +44,11 @@ func BuildSearchResult(ctx context.Context, db *elasticsearch.Client, results in
hits := r["hits"].(map[string]interface{})["hits"].([]interface{})
count = int64(r["hits"].(map[string]interface{})["total"].(map[string]interface{})["value"].(float64))
listResults := make([]interface{}, 0)
idField := modelType.Field(0)
jsonID := idField.Tag.Get("json")
for _, hit := range hits {
r := hit.(map[string]interface{})["_source"]
r.(map[string]interface{})["id"] = hit.(map[string]interface{})["_id"]
r.(map[string]interface{})[jsonID] = hit.(map[string]interface{})["_id"]
stValue := reflect.New(modelType).Elem()
for i := 0; i < modelType.NumField(); i++ {
field := modelType.Field(i)
Expand All @@ -71,23 +73,64 @@ func BuildSearchResult(ctx context.Context, db *elasticsearch.Client, results in
}
}

func BuildSort(s string) []string {
var sort []string
func BuildSort(s string, modelType reflect.Type) []map[string]interface{} {
sort := []map[string]interface{}{}
if len(s) == 0 {
return sort
}
sorts := strings.Split(s, ",")
for i := 0; i < len(sorts); i++ {
sortField := strings.TrimSpace(sorts[i])
fieldName := sortField

var mapFieldName map[string]interface{}
c := sortField[0:1]
if c == "-" || c == "+" {
fieldName = sortField[1:]
//fieldName = sortField[1:]
field, ok := getFieldName(modelType, sortField[1:])
if !ok {
return []map[string]interface{}{}
}
fieldName = field
if c == "-" {
fieldName += ":desc"
mapFieldName = map[string]interface{}{
fieldName: map[string]string{
"order": "desc",
},
}
} else {
mapFieldName = map[string]interface{}{
fieldName: map[string]string{
"order": "asc",
},
}
}
}
sort = append(sort, fieldName)
sort = append(sort, mapFieldName)
}

return sort
}

func getFieldName(structType reflect.Type, jsonTagValue string) (string, bool) {
var (
bsonTagValue string
typeField reflect.Kind
)
for i := 0; i < structType.NumField(); i++ {
field := structType.Field(i)
jsonTag := field.Tag.Get("json")
if jsonTag == jsonTagValue {
bsonTagValue = field.Tag.Get("bson")
typeField = field.Type.Kind()
break
}
}
if bsonTagValue != "_id" {
if typeField == reflect.String {
return "", false
}
return jsonTagValue, true
}
return bsonTagValue, true
}
2 changes: 1 addition & 1 deletion search_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func NewSearchQuery(client *elasticsearch.Client, indexName string, modelType re
func (b *SearchQuery) Search(ctx context.Context, sm interface{}, results interface{}, pageSize int64, skip int64) (int64, error) {
query := b.BuildQuery(sm)
s := b.GetSort(sm)
sort := BuildSort(s)
sort := BuildSort(s, b.ModelType)
total, err := BuildSearchResult(ctx, b.Client, results, b.IndexName, query, sort, pageSize, skip, b.ModelType, b.Map)
return total, err
}
Expand Down

0 comments on commit 12c731f

Please sign in to comment.