github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/sorter/comparable_value_extractor.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package sorter 13 14 import ( 15 "encoding/json" 16 "strconv" 17 "time" 18 19 "github.com/weaviate/weaviate/entities/filters" 20 "github.com/weaviate/weaviate/entities/models" 21 "github.com/weaviate/weaviate/entities/schema" 22 "github.com/weaviate/weaviate/entities/storobj" 23 ) 24 25 type comparableValueExtractor struct { 26 dataTypesHelper *dataTypesHelper 27 } 28 29 func newComparableValueExtractor(dataTypesHelper *dataTypesHelper) *comparableValueExtractor { 30 return &comparableValueExtractor{dataTypesHelper} 31 } 32 33 func (e *comparableValueExtractor) extractFromBytes(objData []byte, propName string) interface{} { 34 value, success, _ := storobj.ParseAndExtractProperty(objData, propName) 35 // in case the property does not exist for the object return nil 36 if len(value) == 0 { 37 return nil 38 } 39 if success { 40 switch e.dataTypesHelper.getType(propName) { 41 case schema.DataTypeBlob: 42 return &value[0] 43 case schema.DataTypeText: 44 return &value[0] 45 case schema.DataTypeTextArray: 46 return &value 47 case schema.DataTypeDate: 48 d := e.mustExtractDates(value[:1])[0] 49 return &d 50 case schema.DataTypeDateArray: 51 da := e.mustExtractDates(value) 52 return &da 53 case schema.DataTypeNumber, schema.DataTypeInt: 54 n := e.mustExtractNumbers(value[:1])[0] 55 return &n 56 case schema.DataTypeNumberArray, schema.DataTypeIntArray: 57 na := e.mustExtractNumbers(value) 58 return &na 59 case schema.DataTypeBoolean: 60 b := e.mustExtractBools(value[:1])[0] 61 return &b 62 case schema.DataTypeBooleanArray: 63 ba := e.mustExtractBools(value) 64 return &ba 65 case schema.DataTypePhoneNumber: 66 fa := e.toFloatArrayFromPhoneNumber(e.mustExtractPhoneNumber(value)) 67 return &fa 68 case schema.DataTypeGeoCoordinates: 69 fa := e.toFloatArrayFromGeoCoordinates(e.mustExtractGeoCoordinates(value)) 70 return &fa 71 default: 72 return nil 73 } 74 } 75 return nil 76 } 77 78 func (e *comparableValueExtractor) extractFromObject(object *storobj.Object, propName string) interface{} { 79 if propName == filters.InternalPropID || propName == filters.InternalPropBackwardsCompatID { 80 id := object.ID().String() 81 return &id 82 } 83 if propName == filters.InternalPropCreationTimeUnix { 84 ts := float64(object.CreationTimeUnix()) 85 return &ts 86 } 87 if propName == filters.InternalPropLastUpdateTimeUnix { 88 ts := float64(object.LastUpdateTimeUnix()) 89 return &ts 90 } 91 92 propertiesMap, ok := object.Properties().(map[string]interface{}) 93 if !ok { 94 return nil 95 } 96 value, ok := propertiesMap[propName] 97 if !ok { 98 return nil 99 } 100 101 switch e.dataTypesHelper.getType(propName) { 102 case schema.DataTypeBlob: 103 s := value.(string) 104 return &s 105 case schema.DataTypeText: 106 s := value.(string) 107 return &s 108 case schema.DataTypeTextArray: 109 sa := value.([]string) 110 return &sa 111 case schema.DataTypeDate: 112 d := e.mustExtractDates([]string{value.(string)})[0] 113 return &d 114 case schema.DataTypeDateArray: 115 da := e.mustExtractDates(value.([]string)) 116 return &da 117 case schema.DataTypeNumber, schema.DataTypeInt: 118 n := value.(float64) 119 return &n 120 case schema.DataTypeNumberArray, schema.DataTypeIntArray: 121 na := value.([]float64) 122 return &na 123 case schema.DataTypeBoolean: 124 b := value.(bool) 125 return &b 126 case schema.DataTypeBooleanArray: 127 ba := value.([]bool) 128 return &ba 129 case schema.DataTypePhoneNumber: 130 fa := e.toFloatArrayFromPhoneNumber(value.(*models.PhoneNumber)) 131 return &fa 132 case schema.DataTypeGeoCoordinates: 133 fa := e.toFloatArrayFromGeoCoordinates(value.(*models.GeoCoordinates)) 134 return &fa 135 default: 136 return nil 137 } 138 } 139 140 func (e *comparableValueExtractor) mustExtractNumbers(value []string) []float64 { 141 numbers := make([]float64, len(value)) 142 for i := range value { 143 number, err := strconv.ParseFloat(value[i], 64) 144 if err != nil { 145 panic("sorter: not a number") 146 } 147 numbers[i] = number 148 } 149 return numbers 150 } 151 152 func (e *comparableValueExtractor) mustExtractBools(value []string) []bool { 153 bools := make([]bool, len(value)) 154 for i := range value { 155 switch value[i] { 156 case "true": 157 bools[i] = true 158 case "false": 159 bools[i] = false 160 default: 161 panic("sorter: not a bool") 162 } 163 } 164 return bools 165 } 166 167 func (e *comparableValueExtractor) mustExtractDates(value []string) []time.Time { 168 dates := make([]time.Time, len(value)) 169 for i := range value { 170 date, err := time.Parse(time.RFC3339, value[i]) 171 if err != nil { 172 panic("sorter: not a date") 173 } 174 dates[i] = date 175 } 176 return dates 177 } 178 179 func (e *comparableValueExtractor) mustExtractPhoneNumber(value []string) *models.PhoneNumber { 180 if len(value) == 1 { 181 var phoneNumber *models.PhoneNumber 182 if err := json.Unmarshal([]byte(value[0]), &phoneNumber); err == nil { 183 return phoneNumber 184 } 185 } 186 panic("sorter: not a phone number") 187 } 188 189 func (e *comparableValueExtractor) mustExtractGeoCoordinates(value []string) *models.GeoCoordinates { 190 if len(value) == 1 { 191 var geoCoordinates *models.GeoCoordinates 192 if err := json.Unmarshal([]byte(value[0]), &geoCoordinates); err == nil { 193 return geoCoordinates 194 } 195 } 196 panic("sorter: not a geo coordinates") 197 } 198 199 func (e *comparableValueExtractor) toFloatArrayFromPhoneNumber(value *models.PhoneNumber) []float64 { 200 return []float64{float64(value.CountryCode), float64(value.National)} 201 } 202 203 func (e *comparableValueExtractor) toFloatArrayFromGeoCoordinates(value *models.GeoCoordinates) []float64 { 204 fa := make([]float64, 2) 205 if value.Longitude != nil { 206 fa[0] = float64(*value.Longitude) 207 } 208 if value.Latitude != nil { 209 fa[1] = float64(*value.Latitude) 210 } 211 return fa 212 }