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  }