package module import ( "errors" "fmt" "strconv" "sync" ) type ItemId string type Item struct { Id ItemId `json:"id"` Name string `json:"name,omitempty"` Score float64 RetrieveId string ItemType string // ItemStatus int Embedding []float64 mutex sync.RWMutex // TimeStamp time.Time Properties map[string]interface{} `json:"properties"` algoScores map[string]float64 } func NewItem(id string) *Item { item := Item{ Id: ItemId(id), Score: 0, Properties: make(map[string]interface{}, 32), } //item.algoScores = make(map[string]float64) return &item } func NewItemWithProperty(id string, properties map[string]interface{}) *Item { item := NewItem(id) for k, v := range properties { item.Properties[k] = v } return item } func (t *Item) GetRecallName() string { return t.RetrieveId } func (t *Item) GetAlgoScores() map[string]float64 { t.mutex.RLock() defer t.mutex.RUnlock() return t.algoScores } func (t *Item) AddProperty(key string, value interface{}) { t.mutex.Lock() defer t.mutex.Unlock() t.Properties[key] = value } func (t *Item) GetProperty(key string) interface{} { t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.Properties[key] if !ok { return nil } return val } func (t *Item) StringProperty(key string) string { t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.Properties[key] if !ok { return "" } switch value := val.(type) { case string: return value case int: return strconv.Itoa(value) case float64: return strconv.Itoa(int(value)) case int32: return strconv.Itoa(int(value)) case int64: return strconv.Itoa(int(value)) } return "" } func (t *Item) FloatProperty(key string) (float64, error) { t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.Properties[key] if !ok { return float64(0), errors.New("property key not exist") } switch value := val.(type) { case float64: return value, nil case int: return float64(value), nil case string: f, err := strconv.ParseFloat(value, 64) return f, err default: return float64(0), errors.New("unspport type") } } func (t *Item) IntProperty(key string) (int, error) { t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.Properties[key] if !ok { return int(0), errors.New("property key not exist") } switch value := val.(type) { case float64: return int(value), nil case int: return value, nil case uint: return int(value), nil case int32: return int(value), nil case int64: return int(value), nil case string: return strconv.Atoi(value) default: return int(0), errors.New("unspport type") } } func (t *Item) AddAlgoScore(name string, score float64) { t.mutex.Lock() defer t.mutex.Unlock() if t.algoScores == nil { t.algoScores = make(map[string]float64) } t.algoScores[name] = score } func (t *Item) FloatExprData(name string) (float64, error) { t.mutex.Lock() defer t.mutex.Unlock() if name == "current_score" { return t.Score, nil } val, ok := t.algoScores[name] if ok { return val, nil } return float64(0), errors.New(fmt.Sprintf("not found,name:%s", name)) } func (t *Item) GetFeatures() map[string]interface{} { t.mutex.Lock() defer t.mutex.Unlock() if t.RetrieveId != "" { if _, ok := t.Properties[t.RetrieveId]; !ok { t.Properties[t.RetrieveId] = t.Score t.Properties["recall_name"] = t.RetrieveId t.Properties["recall_score"] = t.Score } } features := make(map[string]interface{}, len(t.Properties)) for k, v := range t.Properties { features[k] = v } return features } func (t *Item) DeleteProperty(key string) { t.mutex.Lock() defer t.mutex.Unlock() delete(t.Properties, key) } func (t *Item) DeleteProperties(features []string) { t.mutex.Lock() defer t.mutex.Unlock() for _, key := range features { delete(t.Properties, key) } } func (t *Item) AddProperties(properties map[string]interface{}) { t.mutex.Lock() defer t.mutex.Unlock() for key, val := range properties { t.Properties[key] = val } } func (t *Item) DeepClone() *Item { item := NewItemWithProperty(string(t.Id), t.Properties) item.Score = t.Score item.RetrieveId = t.RetrieveId item.ItemType = t.ItemType return item }