| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 | package svcimport (	"fmt"	"strings"	"time"	"golib/features/mlib/ii"	"golib/features/mlib/mo")type Service struct {	usr User}// Svc need prepare mdb.Client and ii.LoadItemInfo first// The second params can not be Nil if called original methodsfunc Svc(user User) *Service {	return &Service{usr: user}}func (c Service) InsertOne(name string, doc interface{}) (mo.ObjectID, error) {	coll, err := c.linkColl(name)	if err != nil {		return mo.NilObjectID, err	}	ctx, cancel := DefaultCtx()	defer cancel()	retId, err := coll.InsertOne(ctx, doc)	if err != nil {		return mo.NilObjectID, err	}	id, ok := retId.InsertedID.(mo.ObjectID)	if ok && !id.IsZero() {		if err = c.insertOneAppendMore(name, id); err == nil {			return id, nil		}	}	del := mo.D{{Key: _Id, Value: id}}	if err = c.DeleteOne(name, del); err != nil {		panic(err)	}	return mo.NilObjectID, mo.ErrNilObjectId}func (c Service) InsertMany(name string, doc []interface{}) ([]mo.ObjectID, error) {	coll, err := c.linkColl(name)	if err != nil {		return nil, err	}	ctx, cancel := DefaultCtx()	defer cancel()	retId, err := coll.InsertMany(ctx, doc)	if err != nil {		return nil, err	}	ids := make([]mo.ObjectID, len(retId.InsertedIDs))	for i := 0; i < len(retId.InsertedIDs); i++ {		id, ok := retId.InsertedIDs[i].(mo.ObjectID)		if ok {			ids[i] = id		} else {			filter := mo.D{{Key: mo.VIn, Value: retId.InsertedIDs}}			if err = c.DeleteMany(name, mo.D{{Key: _Id, Value: filter}}); err == nil {				return nil, fmt.Errorf("ObjectId wrong format")			} else {				return nil, fmt.Errorf("ObjectId wrong format and %s", err)			}		}	}	return ids, c.insertManyAppendMore(name, ids)}func (c Service) FindOne(name string, filter interface{}) (mo.M, error) {	coll, err := c.linkColl(name)	if err != nil {		return nil, err	}	ctx, cancel := DefaultCtx()	defer cancel()	ret := coll.FindOne(ctx, filter)	if err = ret.Err(); err != nil {		return nil, err	}	var result mo.M	return result, ret.Decode(&result)}func (c Service) FindMany(name string, filter interface{}, opts ...*mo.FindOptions) ([]mo.M, error) {	coll, err := c.linkColl(name)	if err != nil {		return nil, err	}	ctx, cancel := DefaultCtx()	defer cancel()	ret, err := coll.Find(ctx, filter, opts...)	if err != nil {		return nil, err	}	var result []mo.M	return result, ret.All(ctx, &result)}func (c Service) UpdateOne(name string, filter, update interface{}) (mo.ObjectID, error) {	coll, err := c.linkColl(name)	if err != nil {		return mo.NilObjectID, err	}	ctx, cancel := DefaultCtx()	defer cancel()	ret := coll.FindOneAndUpdate(ctx, filter, update)	if err = ret.Err(); err != nil {		return mo.NilObjectID, err	}	var r mo.M	if err = ret.Decode(&r); err != nil {		panic(err)	}	return r[_Id].(mo.ObjectID), nil}func (c Service) UpdateById(name string, id mo.ObjectID, update interface{}) (mo.ObjectID, error) {	coll, err := c.linkColl(name)	if err != nil {		return mo.NilObjectID, err	}	ctx, cancel := DefaultCtx()	defer cancel()	ret := coll.FindOneAndUpdate(ctx, mo.D{{Key: _Id, Value: id}}, update)	if err = ret.Err(); err != nil {		return mo.NilObjectID, err	}	var r mo.M	if err = ret.Decode(&r); err != nil {		panic(err)	}	return r[_Id].(mo.ObjectID), nil}func (c Service) UpdateMany(name string, filter, update interface{}) error {	coll, err := c.linkColl(name)	if err != nil {		return err	}	ctx, cancel := DefaultCtx()	defer cancel()	_, err = coll.UpdateMany(ctx, filter, update)	return err}func (c Service) DeleteOne(name string, filter interface{}) error {	coll, err := c.linkColl(name)	if err != nil {		return err	}	ctx, cancel := DefaultCtx()	defer cancel()	_, err = coll.DeleteOne(ctx, filter)	return err}func (c Service) DeleteMany(name string, filter interface{}) error {	coll, err := c.linkColl(name)	if err != nil {		return err	}	ctx, cancel := DefaultCtx()	defer cancel()	_, err = coll.DeleteMany(ctx, filter)	return err}func (c Service) CountDocuments(name string, filter interface{}) (int64, error) {	coll, err := c.linkColl(name)	if err != nil {		return 0, err	}	ctx, cancel := DefaultCtx()	defer cancel()	return coll.CountDocuments(ctx, filter)}func (c Service) Aggregate(name string, pipe mo.Pipeline, opts ...*mo.AggregateOptions) (*mo.Cursor, error) {	coll, err := c.linkColl(name)	if err != nil {		return nil, err	}	ctx, cancel := DefaultCtx()	defer cancel()	return coll.Aggregate(ctx, pipe, opts...)}func (c Service) linkColl(name string) (*mo.Collection, error) {	if !c.usr.Valid() {		return nil, ErrInvalidUser	}	dbName := ii.NewName(name)	return mongoDB.Client().Database(dbName.DbName()).Collection(dbName.CollName()), nil}func (c Service) insertOneAppendMore(name string, id mo.ObjectID) (err error) {	_, err = c.UpdateById(name, id, mo.D{{Key: mo.PSet, Value: mo.D{		{Key: _Creator, Value: c.usr.GetId()},	}}})	return}func (c Service) insertManyAppendMore(name string, id []mo.ObjectID) (err error) {	err = c.UpdateMany(name, mo.D{{Key: _Id, Value: mo.D{{Key: mo.VIn, Value: id}}}}, mo.D{{Key: mo.PSet, Value: mo.D{		{Key: _Creator, Value: c.usr.GetId()},	}}})	return}func (c Service) filterValue(item ii.Item, update map[string]interface{}) error {	for key, value := range update {		field, err := item.GetField(key)		if err != nil {			return err		}		v, err := c.GetValueByType(field.GetType(), value)		if err != nil {			return err		}		update[key] = v	}	return nil}func (c Service) getString(value interface{}) (string, error) {	switch v := value.(type) {	case string:		switch v {		case "curtime":			v = time.Now().Format(mo.DateTimeLayout)		case "curdate":			v = time.Now().Format("2006-01-06")		case "curuser", "cursn", "curusersn":			v = c.usr.GetId().Hex()		case "curusername":			v = c.usr.GetUserName()		case "curname":			v = c.usr.GetName()		default:			if strings.HasPrefix(v, "cur") {				return "", ErrUnknownType(value)			}		}	}	return getFormatString(value), nil}func (c Service) defaultTypeValue(t mo.Type) interface{} {	switch t {	case mo.TypeDouble:		return float64(0)	case mo.TypeString:		return ""	case mo.TypeObject:		return map[string]interface{}{}	case mo.TypeArray:		return []interface{}{}	case mo.TypeBinary:		return []byte{}	case mo.TypeObjectId:		return mo.NilObjectID	case mo.TypeBoolean:		return false	case mo.TypeDate:		return mo.DateTime(0)	case mo.TypeNull:		return nil	case mo.TypeRegex:		return mo.Regex{}	case mo.TypeJavaScript:		return mo.JavaScript("")	case mo.TypeInt:		return int32(0)	case mo.TypeInt64:		return int64(0)	case mo.TypeDecimal128:		f, _ := getDecimal128("0,0")		return f	case mo.TypeMaxKey:		return mo.MaxKey{}	case mo.TypeMinKey:		return mo.MinKey{}	default:		return nil	}}func (c Service) GetValueByType(t mo.Type, v interface{}) (interface{}, error) {	if v == nil {		return c.defaultTypeValue(t), nil	}	switch t {	case mo.TypeDouble:		return getDouble(v)	case mo.TypeString:		return c.getString(v)	case mo.TypeObject:		return getObject(v)	case mo.TypeArray:		return getArray(v)	case mo.TypeBinary:		return getBinary(v)	case mo.TypeObjectId:		return getObjectId(v)	case mo.TypeBoolean:		return getBool(v)	case mo.TypeDate:		return getDate(v)	case mo.TypeNull:		return nil, nil	case mo.TypeRegex:		return getRegex(v)	case mo.TypeJavaScript:		return getJavaScript(v)	case mo.TypeInt:		return getInt32(v)	case mo.TypeInt64:		return getInt64(v)	case mo.TypeDecimal128:		return getDecimal128(v)	case mo.TypeMaxKey:		return mo.MaxKey{}, nil	case mo.TypeMinKey:		return mo.MinKey{}, nil	default:		return nil, ErrUnknownType(v)	}}// TODO 更改为使用原生 Lookup 语句func (c Service) getLookup(field ii.Field, value interface{}) (string, interface{}) {	look, ok := field.GetLookup()	if !ok {		return look.AS, "no_Lookup_value"	}	ret, err := c.FindOne(look.From, mo.D{{Key: look.Condition, Value: mo.D{{Key: mo.VEq, Value: value}}}})	if err != nil {		return look.AS, err.Error()	}	return look.AS, ret[look.Need]}func (c Service) FormatValue(field ii.Field, value interface{}, doc map[string]interface{}) {	switch field.GetModel() {	case ii.TypeDefault:		return	case ii.TypeString:		doc[field.GetName()] = getFormatString(value)	case ii.TypeDate:		doc[field.GetName()] = getFormatDate(value)	case ii.TypeTime:		doc[field.GetName()] = getFormatTime(value)	case ii.TypeInt64:		doc[field.GetName()] = getFormatInt64(value)	case ii.TypeDouble:		doc[field.GetName()] = getFormatFloat64(value)	case ii.TypeLookup:		k, v := c.getLookup(field, value)		doc[k] = v	}	doc[field.GetName()+"_raw"] = value}
 |