package models import ( "pro2d/common/components" "pro2d/common/db/mongoproxy" "pro2d/common/logger" "reflect" "strings" ) type SchemaOption func(schema *Schema) func WithSchemaDB(idb components.IDB) SchemaOption { return func(schema *Schema) { schema.db = idb } } type SchemaMap map[string]components.ISchema type Schema struct { db components.IDB reflectValue *reflect.Value reflectType reflect.Type cacheFields map[string]interface{} pri interface{} schema interface{} } func NewSchema(key string, schema interface{}) *Schema { s := reflect.ValueOf(schema) if s.Kind() == reflect.Ptr { s = reflect.ValueOf(schema).Elem() } sch := &Schema{ reflectValue: &s, reflectType: s.Type(), cacheFields: make(map[string]interface{}), schema: schema, } sch.db = mongoproxy.NewMongoColl(sch.GetSchemaName(), sch) sch.pri = mongoproxy.GetBsonD(sch.getPriTag(), key) return sch } func (s *Schema) FindIndex() (string, []string) { var index []string for i := 0; i < s.reflectType.NumField(); i++ { if s.reflectType.Field(i).Tag.Get("index") != "" { js := strings.Split(s.reflectType.Field(i).Tag.Get("json"), ",") if len(js) == 0 { continue } index = append(index, js[0]) } } return strings.ToLower(s.reflectType.Name()), index } func (s *Schema) Init() { coll, keys := s.FindIndex() for _, index := range keys { s.db.CreateTable() logger.Debug("InitDoc collect: %v, createIndex: %s", coll, index) res, err := s.db.SetUnique(index) if err != nil { logger.Error("InitDoc unique: %s, err: %v", res, err) continue } } } func (s *Schema) GetDB() components.IDB { return s.db } func (s *Schema) GetPri() interface{} { return s.pri } func (s *Schema) GetSchema() interface{} { return s.schema } func (s *Schema) GetSchemaName() string { return strings.ToLower(s.reflectType.Name()) } func (s *Schema) Load() error { return s.db.Load() } func (s *Schema) Create() error { _, err := s.db.Create() return err } func (s *Schema) Save() error { return s.db.Save() } func (s *Schema) Update() { if s.cacheFields != nil { s.db.UpdateProperties(s.cacheFields) s.cacheFields = make(map[string]interface{}) } } func (s *Schema) SetProperty(key string, val interface{}) { s.reflectValue.FieldByName(key).Set(reflect.ValueOf(val)) s.cacheFields[strings.ToLower(key)] = val } func (s *Schema) SetProperties(properties map[string]interface{}) { for key, val := range properties { s.reflectValue.FieldByName(key).Set(reflect.ValueOf(val)) s.cacheFields[strings.ToLower(key)] = val } } func (s *Schema) getPriTag() string { var pri string for i := 0; i < s.reflectType.NumField(); i++ { if s.reflectType.Field(i).Tag.Get("pri") == "1" { pri = strings.ToLower(s.reflectType.Field(i).Name) break } } return pri }