github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/model/index.go (about) 1 package model 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // Index represents a data model index for fast access 9 type Index struct { 10 FieldName string 11 // Type of index, eg. equality 12 Type string 13 Order Order 14 // Do not allow duplicate values of this field in the index. 15 // Useful for emails, usernames, post slugs etc. 16 Unique bool 17 // Strings for ordering will be padded to a fix length 18 // Not a useful property for Querying, please ignore this at query time. 19 // Number is in bytes, not string characters. Choose a sufficiently big one. 20 // Consider that each character might take 4 bytes given the 21 // internals of reverse ordering. So a good rule of thumbs is expected 22 // characters in a string X 4 23 StringOrderPadLength int 24 // True = base32 encode ordered strings for easier management 25 // or false = keep 4 bytes long runes that might dispaly weirdly 26 Base32Encode bool 27 28 FloatFormat string 29 Float64Max float64 30 Float32Max float32 31 } 32 33 // Order is the order of the index 34 type Order struct { 35 FieldName string 36 // Ordered or unordered keys. Ordered keys are padded. 37 // Default is true. This option only exists for strings, where ordering 38 // comes at the cost of having rather long padded keys. 39 Type OrderType 40 } 41 42 func (i Index) ToQuery(value interface{}) Query { 43 return Query{ 44 Index: i, 45 Value: value, 46 Order: i.Order, 47 } 48 } 49 50 // ByEquality constructs an equiality index on `fieldName` 51 func ByEquality(fieldName string) Index { 52 return Index{ 53 FieldName: fieldName, 54 Type: indexTypeEq, 55 Order: Order{ 56 Type: OrderTypeAsc, 57 FieldName: fieldName, 58 }, 59 StringOrderPadLength: 16, 60 Base32Encode: false, 61 FloatFormat: "%019.5f", 62 Float64Max: 92233720368547, 63 Float32Max: 922337, 64 } 65 } 66 67 func indexMatchesQuery(i Index, q Query) bool { 68 if strings.ToLower(i.FieldName) == strings.ToLower(q.FieldName) && 69 i.Type == q.Type && 70 i.Order.Type == q.Order.Type { 71 return true 72 } 73 return false 74 } 75 76 func indexesMatch(i, j Index) bool { 77 if i.FieldName == j.FieldName && 78 i.Type == j.Type && 79 i.Order.Type == j.Order.Type { 80 return true 81 } 82 return false 83 } 84 85 // indexPrefix returns the first part of the keys, the namespace + index name 86 func indexPrefix(i Index) string { 87 var ordering string 88 switch i.Order.Type { 89 case OrderTypeUnordered: 90 ordering = "Unord" 91 case OrderTypeAsc: 92 ordering = "Asc" 93 case OrderTypeDesc: 94 ordering = "Desc" 95 } 96 typ := i.Type 97 // hack for all listing where we use the eq ID index 98 // without a value to list all 99 if i.Type == indexTypeAll { 100 typ = indexTypeEq 101 } 102 orderingField := i.Order.FieldName 103 if len(orderingField) == 0 { 104 orderingField = i.FieldName 105 } 106 filterField := i.FieldName 107 return fmt.Sprintf("%vBy%v%vBy%v", typ, strings.Title(filterField), ordering, strings.Title(orderingField)) 108 } 109 110 func newIndex(v string) Index { 111 idIndex := ByEquality(v) 112 idIndex.Order.Type = OrderTypeUnordered 113 return idIndex 114 }