-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquery.go
123 lines (116 loc) · 3.73 KB
/
query.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package dynamodb
import (
"context"
"fmt"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"github.com/aws/aws-sdk-go/service/dynamodb/expression"
"reflect"
"strings"
)
func BuildSearchResult(ctx context.Context, db *dynamodb.DynamoDB, results interface{}, query dynamodb.ScanInput, limit int64, pageIndex int64, options ...func(context.Context, interface{}) (interface{}, error)) (int64, error) {
var databaseQuery *dynamodb.ScanOutput
var mp func(context.Context, interface{}) (interface{}, error)
if len(options) > 0 && options[0] != nil {
mp = options[0]
}
if pageIndex < 1 {
pageIndex = 1
}
if limit <= 0 {
_, er0 := FindAndDecode(ctx, db, &query, results)
return 0, er0
}
query.SetLimit(limit)
pageNum := 0
err := db.ScanPagesWithContext(ctx, &query,
func(page *dynamodb.ScanOutput, lastPage bool) bool {
pageNum++
if pageNum == int(pageIndex) {
databaseQuery = page
}
return pageNum <= int(pageIndex)
})
if err != nil {
return 0, err
}
err = dynamodbattribute.UnmarshalListOfMaps(databaseQuery.Items, &results)
if err != nil {
return 0, err
}
count := *databaseQuery.Count
if mp == nil {
return count, nil
}
_, er3 := MapModels(ctx, results, mp)
return count, er3
}
func BuildKeyCondition(sm interface{}, index SecondaryIndex, keyword string) (expression.KeyConditionBuilder, error) {
var keyCondition *expression.KeyConditionBuilder
var keyConditionBuilders []*expression.KeyConditionBuilder
objectValue := reflect.Indirect(reflect.ValueOf(sm))
objectModel := objectValue.Type()
for _, key := range index.Keys {
if i, _, ok := GetFieldByTagName(objectModel, key); ok {
fieldValue := reflect.Indirect(objectValue.Field(i))
if fieldValue.Kind() == reflect.String {
var builder expression.KeyConditionBuilder
if fieldValue.Len() > 0 {
if key, ok := objectValue.Type().Field(i).Tag.Lookup("match"); ok {
if key == PREFIX {
builder = expression.Key(key).BeginsWith(fieldValue.String())
} else {
return *keyCondition, fmt.Errorf("match not support \"%v\" format\n", key)
}
}
} else if len(keyword) > 0 {
if key, ok := objectValue.Type().Field(i).Tag.Lookup("keyword"); ok {
if key == PREFIX {
builder = expression.Key(key).BeginsWith(fieldValue.String())
} else {
return *keyCondition, fmt.Errorf("match not support \"%v\" format\n", key)
}
}
}
keyConditionBuilders = append(keyConditionBuilders, &builder)
} else {
t := fieldValue.Kind().String()
if (strings.Contains(t, "int") && fieldValue.Int() != 0) || (strings.Contains(t, "float") && fieldValue.Float() != 0) {
builder := expression.Key(key).Equal(expression.Value(fieldValue.Interface()))
keyConditionBuilders = append(keyConditionBuilders, &builder)
} else {
return *keyCondition, fmt.Errorf("key condition not support \"%v\" type\n", key)
}
}
}
}
for idx := range keyConditionBuilders {
if keyCondition == nil {
keyCondition = keyConditionBuilders[idx]
} else {
keyCondition.And(*keyConditionBuilders[idx])
}
}
return *keyCondition, nil
}
func MapModels(ctx context.Context, models interface{}, mp func(context.Context, interface{}) (interface{}, error)) (interface{}, error) {
valueModelObject := reflect.Indirect(reflect.ValueOf(models))
if valueModelObject.Kind() == reflect.Ptr {
valueModelObject = reflect.Indirect(valueModelObject)
}
if valueModelObject.Kind() == reflect.Slice {
le := valueModelObject.Len()
for i := 0; i < le; i++ {
x := valueModelObject.Index(i)
k := x.Kind()
if k == reflect.Struct {
y := x.Addr().Interface()
mp(ctx, y)
} else {
y := x.Interface()
mp(ctx, y)
}
}
}
return models, nil
}