package module import ( "errors" "strconv" "sync" "gitlab.alibaba-inc.com/pai_biz_arch/pairec/context" ) type User struct { Id UID `json:"uid"` Vector string Properties map[string]interface{} `json:"properties"` mutex sync.RWMutex } func NewUser(id string) *User { user := User{ Id: UID(id), } user.Properties = make(map[string]interface{}) return &user } func NewUserWithContext(id UID, context *context.RecommendContext) *User { user := NewUser(string(id)) user.AddProperty("uid", string(id)) features := context.GetParameter("features") if features != nil { if _, ok := features.(map[string]interface{}); ok { for k, v := range features.(map[string]interface{}) { user.AddProperty(k, v) } } } return user } func (u *User) AddProperty(key string, value interface{}) { u.mutex.Lock() u.Properties[key] = value u.mutex.Unlock() } func (u *User) FloatProperty(key string) (float64, error) { //u.mutex.RLock() //defer u.mutex.RUnlock() val, ok := u.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 (u *User) MakeUserFeatures() (features map[string]interface{}) { features = make(map[string]interface{}) for k, v := range u.Properties { if k == "type" { continue } if s, ok := v.(float64); ok { features[k] = s continue } if str, ok := v.(string); ok { if s, err := strconv.ParseFloat(str, 64); err == nil { features[k] = s continue } } features[k] = v } return } // MakeUserFeatures2 for easyrec processor func (u *User) MakeUserFeatures2() (features map[string]interface{}) { features = make(map[string]interface{}, len(u.Properties)) for k, v := range u.Properties { features[k] = v } return } func (u *User) StringProperty(key string) string { u.mutex.RLock() defer u.mutex.RUnlock() val, ok := u.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)) } return "" } func (u *User) DeleteProperty(key string) { u.mutex.Lock() delete(u.Properties, key) u.mutex.Unlock() } func (u *User) DeleteProperties(features []string) { u.mutex.Lock() for _, key := range features { delete(u.Properties, key) } u.mutex.Unlock() } func (u *User) IntProperty(key string) (int, error) { //u.mutex.RLock() //defer u.mutex.RUnlock() val, ok := u.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 (u *User) GetProperty(key string) interface{} { //u.mutex.RLock() //defer u.mutex.RUnlock() val, ok := u.Properties[key] if !ok { return nil } return val }