12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565 |
- package api
- import (
- "bytes"
- "context"
- "encoding/base64"
- "fmt" // "html/template"
- "reflect"
- "regexp"
- "strconv"
- "strings"
- "text/template"
- "time"
- "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/api/errs"
- "github.com/davecgh/go-spew/spew"
- "github.com/kataras/iris"
- iriscontext "github.com/kataras/iris/v12/context"
- "go.mongodb.org/mongo-driver/bson"
- "go.mongodb.org/mongo-driver/bson/primitive"
- "go.mongodb.org/mongo-driver/mongo"
- "go.mongodb.org/mongo-driver/mongo/options"
- "go.mongodb.org/mongo-driver/mongo/readconcern"
- "go.mongodb.org/mongo-driver/mongo/readpref"
- "go.mongodb.org/mongo-driver/mongo/writeconcern"
- )
- const (
- DefaultAddrConnect = "mongodb://localhost:27017"
- InsertOne = iota + 1
- InsertMany
- Patch
- )
- var (
- QueriesMap = map[string]*template.Template{}
- EMPTYQUERY_REGEX = regexp.MustCompile(`{\s*}`)
- )
- func GetSessionContext(ctx iriscontext.Context) mongo.SessionContext {
- context := ctx.Values().Get("$SessionContext")
- if context != nil {
- return context.(mongo.SessionContext)
- }
- return nil
- }
- func init() {
- errs.RegisterMapErrorFunction("MONGO_ERROS", func(source error) (err *errs.Error) {
- message := source.Error()
- switch {
- case strings.Contains(message, "E11000"):
- err = errs.AlreadyExists().Details(&errs.Detail{
- Message: "DUPLICATED_ITEM",
- })
- case strings.Contains(message, "cannot decode"):
- err = errs.DataCaps().Details(&errs.Detail{
- Message: message,
- })
- case strings.Contains(message, "no documents in result"):
- errs.NotFound().Details(&errs.Detail{
- Message: "NOT_FOUND",
- })
- }
- return
- })
- }
- type Mongo struct {
- // Sessions map[string]*mgo.Session
- // Session *mgo.Session
- // Uri string
- // Configs
- //DefaultDB string
- // User string `json:"user"`
- // Password string `json:"password"`
- // DataBase string `json:"database"`
- // Addrs string `json:"addrs"`
- subject *BehaviorSubjectStruct
- client *mongo.Client
- Credential *options.Credential
- Config string `json:"config"`
- Clients map[string]*mongo.Client
- }
- type execfn func(context.Context, *mongo.Collection)
- type EntityInterface interface {
- Patch() *bson.A
- }
- // Modelo de comunicação entre o controle da API e a camada de persistencia.
- type Filter struct {
- Id primitive.ObjectID
- UserId primitive.ObjectID
- // NextPageToken primitive.ObjectID
- // PageToken PageToken
- Fields *bson.M
- Query *bson.M
- Patchs *bson.A
- Sort *bson.M
- Context *iriscontext.Context
- // Sort []string
- Collection string
- QueryType string
- DB string
- Format string
- Insertion int
- CheckQuery bool
- IgnoreNoEntityFound bool
- MaxResults int
- Entity interface{}
- Entities interface{}
- SessionContext mongo.SessionContext
- // Aggregate interface{}
- Pipeline primitive.A
- Options interface{}
- }
- func (f *Filter) Aggregate(ctx context.Context, collection *mongo.Collection, opts *options.AggregateOptions) (cursor *mongo.Cursor, err *errs.Error) {
- var errl error
- if opts == nil {
- opts = options.Aggregate().SetBatchSize(int32(f.MaxResults))
- }
- // cmd := command.Aggregate{
- // NS: ns,
- // Pipeline: pipeline,
- // ReadPref: rp,
- // }
- if cursor, errl = collection.Aggregate(ctx, f.Pipeline, opts); errl != nil {
- err = errs.FromError(errl)
- }
- return
- }
- func (t *Filter) Check() (err *errs.Error) {
- if t.CheckQuery {
- if t.Query == nil {
- if !t.Id.IsZero() {
- t.Query = &bson.M{"_id": t.Id}
- } else {
- err = errs.InvalidArgument().Details(&errs.Detail{
- LocationType: "query",
- Location: "q",
- Message: "emptyValue",
- })
- return
- }
- }
- }
- if t.Query == nil {
- t.Query = &bson.M{}
- }
- return
- }
- func (t *Mongo) Ready() *BehaviorSubjectStruct {
- if t.subject == nil {
- t.subject = BehaviorSubject()
- }
- return t.subject
- }
- func (t *Mongo) Init() (err error) {
- defer func() {
- spew.Dump(err)
- }()
- fmt.Printf("Connection string '%s'", t.Config)
- clientOpts := options.Client().ApplyURI(t.Config)
- if t.Credential != nil {
- clientOpts.SetAuth(*t.Credential)
- }
- connectContext, _ := context.WithTimeout(context.Background(), 10*time.Second)
- // if t.client, err = mongo.NewClient(setOptions); err != nil {
- if t.client, err = mongo.Connect(
- connectContext,
- clientOpts,
- ); err != nil {
- return
- }
- // ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
- // defer cancel()
- // if err = t.client.Connect(ctx); err != nil {
- // return
- // }
- t.Ready().Next(true)
- return nil
- }
- func (t *Mongo) CommitTransaction(opts *options.SessionOptions) {
- }
- func (t *Mongo) StartTransaction(
- sessionOptions *options.SessionOptions,
- transactionOptions *options.TransactionOptions,
- ) (
- sessionContext mongo.SessionContext,
- err *errs.Error,
- ) {
- var (
- session mongo.Session
- localError error
- )
- defer func() {
- if localError != nil {
- err = errs.Internal().Details(&errs.Detail{
- Message: localError.Error(),
- })
- }
- }()
- if session, localError = t.client.StartSession(sessionOptions); localError == nil {
- ctx, _ := context.WithTimeout(context.Background(), 60*time.Second)
- mongo.WithSession(ctx, session, func(sctx mongo.SessionContext) error {
- if localError = session.StartTransaction(transactionOptions); localError == nil {
- sessionContext = sctx
- }
- return nil
- })
- }
- return
- }
- func (t *Mongo) Dispatch(f *Filter) {
- }
- func (t *Mongo) InsertOne(f *Filter) (res *mongo.InsertOneResult, err *errs.Error) {
- defer func() {
- event := createDebugEvent(f, "models.insert.one")
- event.Error = err
- }()
- f.Insertion = InsertOne
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- var lerr error
- if res, lerr = collection.InsertOne(ctx, f.Entity); lerr != nil {
- err = errs.FromError(lerr)
- }
- }, func(e *errs.Error) { err = e })
- return
- }
- func (t *Mongo) InsertMany(f *Filter) (res *mongo.InsertManyResult, err *errs.Error) {
- defer func() {
- event := createDebugEvent(f, "models.insert.many")
- event.Error = err
- }()
- f.Insertion = InsertMany
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- var (
- lerr error
- entities []interface{}
- value = reflect.ValueOf(f.Entities)
- )
- for index := 0; index < value.Len(); index++ {
- entities = append(entities, value.Index(index).Interface())
- }
- if res, lerr = collection.InsertMany(ctx, entities); lerr != nil {
- err = errs.FromError(lerr)
- }
- }, func(e *errs.Error) { err = e })
- return
- }
- //Remove os elementos da colecao, selecionados pela query
- func (t *Mongo) RemoveOne(f *Filter) (res *mongo.DeleteResult, err *errs.Error) {
- defer func() {
- event := createDebugEvent(f, "models.remove.one")
- event.Error = err
- }()
- f.CheckQuery = true
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- var lerr error
- if res, lerr = collection.DeleteOne(ctx, f.Query); lerr != nil {
- err = errs.FromError(lerr)
- } else if res.DeletedCount == 0 {
- err = errs.NotFound().Details(&errs.Detail{
- Message: "No entity has been deleted",
- })
- }
- }, func(e *errs.Error) { err = e })
- return
- }
- //Remove os elementos da colecao, selecionados pela query
- func (t *Mongo) RemoveMany(f *Filter) (res *mongo.DeleteResult, err *errs.Error) {
- var lerr error
- defer func() {
- event := createDebugEvent(f, "models.remove.many")
- event.Error = err
- }()
- f.CheckQuery = true
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- if res, lerr = collection.DeleteMany(ctx, f.Entities); lerr != nil {
- err = errs.FromError(lerr)
- } else if res.DeletedCount == 0 {
- err = errs.NotFound().Details(&errs.Detail{
- Message: "No entity has been deleted",
- })
- }
- }, func(e *errs.Error) { err = e })
- return
- }
- func (t *Mongo) UpdateOne(f *Filter) (res *mongo.UpdateResult, err *errs.Error) {
- var lerr error
- defer func() {
- event := createDebugEvent(f, "models.update.one")
- event.Error = err
- }()
- f.Insertion = InsertOne
- f.CheckQuery = true
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- if res, lerr = collection.ReplaceOne(ctx, f.Query, f.Entity); lerr != nil {
- err = errs.FromError(lerr)
- } else if !f.IgnoreNoEntityFound && (res.ModifiedCount+res.UpsertedCount) == 0 {
- err = errs.NotFound().Details(&errs.Detail{
- Message: "No entity has been updated",
- })
- }
- }, func(e *errs.Error) { err = e })
- return
- }
- func (t *Mongo) UpdateMany(f *Filter) (res *mongo.UpdateResult, err *errs.Error) {
- var (
- lerr error
- entity interface{}
- entities []interface{}
- value = reflect.ValueOf(f.Entities)
- )
- defer func() {
- event := createDebugEvent(f, "models.update.many")
- event.Error = err
- }()
- f.Insertion = InsertMany
- f.CheckQuery = true
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- for index := 0; index < value.Len(); index++ {
- entity = value.Index(index).Interface()
- entities = append(entities, entity)
- }
- if res, lerr = collection.UpdateMany(ctx, f.Query, entities); lerr != nil {
- err = errs.FromError(lerr)
- } else if !f.IgnoreNoEntityFound && (res.ModifiedCount+res.UpsertedCount) == 0 {
- err = errs.NotFound().Details(&errs.Detail{
- Message: "No entity has been updated ",
- })
- }
- }, func(e *errs.Error) { err = e })
- return
- }
- func RegisterQuery(id, query string) {
- QueriesMap[id] = template.Must(template.New(id).Parse(query))
- }
- func ParseQuery(ctx iriscontext.Context, filter *Filter, basequery string, data map[string]interface{}) (err *errs.Error) {
- var (
- found bool
- templateErr error
- buf bytes.Buffer
- baseQueryTemplate *template.Template
- // baseQeuryDocument *bson.M
- // errbq *errs.Error
- queryDecodedString []byte
- userQueryString = Q(ctx, "q", "e30=") // default base64 encoded from "{}"
- includeInTrash, _ = strconv.ParseBool(Q(ctx, "includeInTrash", "false")) // default base64 encoded from "{}"
- )
- // defer func() {
- // spew.Dump(filter.Query)
- // }()
- // Faz o parse da userQueryString enviada pelo usuario que deve ser um base64
- if queryDecodedString, templateErr = base64.StdEncoding.DecodeString(userQueryString); templateErr != nil {
- err = errs.InvalidArgument().Details(&errs.Detail{
- Message: "Query param isn't a base64 json",
- })
- return
- }
- if baseQueryTemplate, found = QueriesMap[basequery]; !found {
- err = errs.Internal().Details(&errs.Detail{
- Message: "Invalid query input",
- })
- return
- }
- // transclude the query to base query
- data["_transclude_"] = string(queryDecodedString)
- data["_deleted_"] = includeInTrash
- fmt.Println(
- basequery,
- string(queryDecodedString),
- data,
- )
- if templateErr = baseQueryTemplate.Execute(&buf, data); templateErr != nil {
- err = errs.InvalidArgument().Details(&errs.Detail{
- Message: "Failed on interpolate data with template query",
- })
- return
- }
- x := buf.Bytes()
- fmt.Println("buf.Bytes()", string(x))
- if templateErr = bson.UnmarshalExtJSON(x, false, &filter.Query); templateErr != nil {
- err = errs.InvalidArgument().Details(&errs.Detail{
- Message: "Failed on interpolate data with template query",
- })
- return
- }
- return
- }
- func (t *Mongo) PatchOne(f *Filter) (res *mongo.UpdateResult, err *errs.Error) {
- defer func() {
- event := createDebugEvent(f, "models.patch.one")
- event.Error = err
- }()
- f.Insertion = Patch
- f.CheckQuery = true
- // out, _ := json.Marshal()
- // fmt.Println(string(out))
- // spew.Dump(f.Patchs)
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- var (
- lerr error
- // client *mongo.Client
- )
- // if client, err = t.GetClient(f.DB); err != nil {
- // return
- // }
- // spew.Dump(f.Query)
- // spew.Dump(f.Patchs)
- // id := primitive.NewObjectID()
- t.client.UseSessionWithOptions(
- ctx,
- options.Session().SetDefaultReadPreference(readpref.Primary()),
- func(sctx mongo.SessionContext) error {
- defer func() {
- if err != nil {
- // fmt.Println("abort patch ", id.Hex())
- sctx.AbortTransaction(sctx)
- } else {
- // fmt.Println("commit patch ", id.Hex())
- sctx.CommitTransaction(sctx)
- }
- sctx.EndSession(sctx)
- }()
- sctx.StartTransaction(options.Transaction().
- SetReadConcern(readconcern.Snapshot()).
- SetWriteConcern(writeconcern.New(writeconcern.WMajority())))
- for _, p := range *f.Patchs {
- if f.Options == nil {
- f.Options = options.Update()
- }
- if res, lerr = collection.UpdateOne(ctx, f.Query, p, f.Options.(*options.UpdateOptions)); lerr != nil {
- err = errs.FromError(lerr)
- return lerr
- }
- if !f.IgnoreNoEntityFound && (res.ModifiedCount+res.UpsertedCount) == 0 {
- err = errs.NotFound().Details(&errs.Detail{
- Message: "No entity has been updated",
- })
- return fmt.Errorf("No entity has been updated")
- }
- }
- return nil
- },
- )
- }, func(e *errs.Error) { err = e })
- return
- }
- func (t *Mongo) PatchMany(f *Filter) (res *mongo.UpdateResult, err *errs.Error) {
- defer func() {
- event := createDebugEvent(f, "models.patch.many")
- event.Error = err
- }()
- f.Insertion = Patch
- f.CheckQuery = true
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- var (
- lerr error
- // client *mongo.Client
- )
- // if client, err = t.GetClient(f.DB); err != nil {
- // return
- // }
- // o, _ := json.MarshalIndent(f.Query, "", " ")
- // fmt.Println("query", o)
- // o, _ = json.MarshalIndent(f.Patchs, "", " ")
- // fmt.Println("patch", o)
- t.client.UseSessionWithOptions(
- ctx,
- options.Session().SetDefaultReadPreference(readpref.Primary()),
- func(sctx mongo.SessionContext) error {
- defer func() {
- if err != nil {
- sctx.AbortTransaction(sctx)
- } else {
- sctx.CommitTransaction(sctx)
- }
- sctx.EndSession(sctx)
- }()
- sctx.StartTransaction(
- options.Transaction().
- SetReadConcern(readconcern.Snapshot()).
- SetWriteConcern(writeconcern.New(writeconcern.WMajority())),
- )
- for _, p := range *f.Patchs {
- if res, lerr = collection.UpdateMany(ctx, f.Query, p); lerr != nil {
- err = errs.FromError(lerr)
- return lerr
- }
- if !f.IgnoreNoEntityFound && (res.ModifiedCount+res.UpsertedCount) == 0 {
- err = errs.NotFound().Details(&errs.Detail{
- Message: "No entity has been updated",
- })
- err.CodeText = "noEntityUpdated"
- return fmt.Errorf("No entity has been updated")
- }
- }
- return nil
- },
- )
- }, func(e *errs.Error) { err = e })
- return
- }
- func (mongo *Mongo) CreateIndex(database, collectionString string, index mongo.IndexModel) *errs.Error {
- collection := mongo.client.Database(database).Collection(collectionString)
- opts := options.CreateIndexes().SetMaxTime(10 * time.Second)
- if _, err := collection.Indexes().CreateOne(context.Background(), index, opts); err != nil {
- return errs.FromError(err)
- }
- return nil
- }
- func (mongo *Mongo) FindOneRx(options *Filter) *ObservableStruct {
- return Observable(func(observer *Subscriber) {
- if res, err := mongo.FindOne(options); err != nil {
- observer.Err(err)
- } else {
- observer.Next(res)
- }
- })
- }
- func (t *Mongo) FindOne(f *Filter) (res *mongo.SingleResult, err *errs.Error) {
- defer func() {
- event := createDebugEvent(f, "models.find.one")
- event.Error = err
- }()
- f.CheckQuery = (f.QueryType != "aggregate")
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- var (
- lerr error
- cursor *mongo.Cursor
- )
- if f.QueryType == "aggregate" {
- if cursor, err = f.Aggregate(ctx, collection, nil); err != nil {
- return
- }
- if cursor.Next(ctx) {
- if lerr = cursor.Decode(f.Entity); lerr == nil {
- return
- }
- } else {
- lerr = fmt.Errorf("No document found")
- }
- } else {
- res = collection.FindOne(ctx, f.Query)
- if lerr = res.Err(); lerr == nil {
- if lerr = res.Decode(f.Entity); lerr == nil {
- return
- }
- }
- }
- err = errs.FromError(lerr)
- }, func(e *errs.Error) {
- err = e
- })
- return
- }
- func findIds(filter *Filter) (ids []primitive.ObjectID) {
- ids = []primitive.ObjectID{}
- // findIdsFilter = &Filter{}
- // cursor, err := executeFind(findIdsFilter)
- return
- }
- func (t *Mongo) FindMany(f *Filter) (cursor *mongo.Cursor, err *errs.Error) {
- // f.CheckQuery = true
- defer func() {
- event := createDebugEvent(f, "models.find.many")
- event.Error = err
- }()
- t.exec(f, func(ctx context.Context, collection *mongo.Collection) {
- var (
- lerr error
- elemp reflect.Value
- // ids = []primitive.ObjectID{}
- // limit = int64(f.MaxResults)
- // fields = f.Fields
- )
- // defer func() {
- // if errd := recover(); errd != nil {
- // // fmt.Println(errd)
- // // spew.Dump(Trace())
- // // fmt.Println(errors.WithStack(errd.(error)) )
- // LogError(0, fmt.Sprintf("FindMany - %v", errd))
- // }
- // }()
- // Carrega os ids e verifica o intervalo de paginacao da consulta.
- // f.Fields = &bson.M{"_id": 1}
- // ids = findIds(f)
- // Atualiza a consulta para o conjunto de ids da paginacao
- // f.Fields = fields
- // f.Query = &bson.M{"_id": bson.M{"$in": ids}}
- // fmt.Println("Query Type ", f.QueryType)
- if f.QueryType == "aggregate" {
- cursor, lerr = f.Aggregate(ctx, collection, nil)
- } else {
- findOptions := options.Find()
- findOptions.SetLimit(int64(f.MaxResults))
- // fmt.Printf("sort of query '%s'\n", f.Format)
- // spew.Dump(f.Sort)
- // spew.Dump(f.Fields)
- // spew.Dump(f.Query)
- if f.Sort != nil {
- findOptions.SetSort(f.Sort)
- }
- if f.Fields != nil {
- findOptions.SetProjection(f.Fields)
- }
- cursor, lerr = collection.Find(ctx, f.Query, findOptions)
- }
- if lerr == nil {
- defer cursor.Close(ctx)
- // spew.Dump(cursor)
- if f.Entities == nil {
- lerr = fmt.Errorf("Entities can't be nil")
- goto FindManyError
- }
- entitiesValue := reflect.ValueOf(f.Entities)
- if entitiesValue.Kind() != reflect.Ptr || entitiesValue.Elem().Kind() != reflect.Slice {
- lerr = fmt.Errorf("Entities argument must be a slice address")
- goto FindManyError
- }
- slicev := entitiesValue.Elem()
- slicev = slicev.Slice(0, slicev.Cap())
- typ := slicev.Type().Elem()
- for cursor.Next(ctx) {
- elemp = reflect.New(typ)
- // fmt.Println("aqui")
- if lerr = cursor.Decode(elemp.Interface()); lerr != nil {
- // spew.Dump(elemp)
- goto FindManyError
- }
- slicev = reflect.Append(slicev, elemp.Elem())
- }
- // spew.Dump(slicev)
- entitiesValue.Elem().Set(slicev)
- return
- }
- FindManyError:
- err = errs.FromError(lerr)
- }, func(e *errs.Error) { err = e })
- return
- }
- func createDebugEvent(options *Filter, eventType string) *DebugEvent {
- debug := options.Context.Values().Get("#debug")
- event := debug.Event(eventType)
- event.Data = iris.Map{}
- return event
- }
- func (models *Mongo) Exists(options *Filter) (exists bool, err *errs.Error) {
- defer func() {
- event := createDebugEvent(options, "models.exists")
- event.Data = iris.Map{"response": exists}
- event.Error = err
- }()
- options.Fields = &bson.M{"_id": 1}
- if _, err = models.FindOne(options); err != nil {
- return
- }
- exists = true
- return
- }
- func (driver *Mongo) GetContext(options *Filter) (context.Context, *mongo.Collection) {
- var ctx context.Context
- if options.SessionContext != nil {
- ctx = options.SessionContext
- } else {
- ctx, _ = context.WithTimeout(context.Background(), 40*time.Second)
- }
- collection := driver.client.Database(options.DB).Collection(options.Collection)
- return ctx, collection
- }
- func (t *Mongo) exec(f *Filter, execAction execfn, errorAction func(*errs.Error)) {
- var (
- err *errs.Error
- errl error
- ctx context.Context
- // client *mongo.Client
- )
- defer func() {
- if err == nil {
- if errl == nil {
- return
- }
- err = errs.FromError(errl)
- }
- // spew.Dump(err)
- errorAction(err)
- }()
- if err = f.Check(); err != nil {
- return
- }
- switch f.Insertion {
- case InsertOne:
- if f.Entity == nil {
- errl = fmt.Errorf("Entity can't be nil")
- return
- }
- case InsertMany:
- if f.Entities == nil {
- errl = fmt.Errorf("Entities can't be nil")
- return
- }
- case Patch:
- if f.Patchs == nil {
- errl = fmt.Errorf("Patchs can't be nil")
- return
- }
- }
- // fmt.Println("passei do exec")
- if f.SessionContext != nil {
- ctx = f.SessionContext
- } else {
- ctx, _ = context.WithTimeout(context.Background(), time.Minute)
- }
- collection := t.client.Database(f.DB).Collection(f.Collection)
- execAction(ctx, collection)
- return
- }
- func DeletedPatch() *bson.A {
- return &bson.A{
- bson.M{
- "$set": bson.M{
- "deleted": true,
- "deletedIn": time.Now().Unix(),
- },
- },
- }
- }
- // func mergeQueries(filter *Filter) *bson.M {
- // if baseQeuryDocument != nil {
- // if filter.Query == nil {
- // filter.Query = baseQeuryDocument
- // } else {
- // filter.Query = &bson.M{
- // "$and": bson.A{baseQeuryDocument, filter.Query},
- // }
- // }
- // } else if filter.Query == nil {
- // filter.Query = &bson.M{}
- // }
- // }
- // func yieldIndexModel() mongo.IndexModel {
- // keys := bsonx.Doc{{Key: *key, Value: bsonx.Int32(int32(*value))}}
- // index := mongo.IndexModel{}
- // index.Keys = keys
- // if *unique {
- // index.Options = bsonx.Doc{{Key: "unique", Value: bsonx.Boolean(true)}}
- // }
- // return index
- // }
- // func (t *Mongo) GetClient() (*mgo.Session, *errs.Error) {
- // func (t *Mongo) GetClient(id string) (*mongo.Client, *errs.Error) {
- // var (
- // client *mongo.Client
- // found bool
- // )
- // if id == "" {
- // panic("Client id not defined!")
- // }
- // if client, found = t.Clients[id]; !found {
- // return nil, FullError(ERR_SERVICE_UNAVAILABLE, &errs.Detail{
- // Message: fmt.Sprintf("Client %s not exists!", id),
- // })
- // }
- // return client, nil
- // }
- // func errorcheck(err error) *errs.Error {
- // if err != nil {
- // return FullError(ERR_GENERAL, &errs.Detail{
- // Message: err.Error(),
- // })
- // }
- // return nil
- // }
- // func Paginate(collection *mongo.Collection, startValue primitive.ObjectID, nPerPage int64) ([]bson.D, *bson.Value, error) {
- // // Query range filter using the default indexed _id field.
- // filter := bson.VC.DocumentFromElements(
- // bson.EC.SubDocumentFromElements(
- // "_id",
- // bson.EC.ObjectID("$gt", startValue),
- // ),
- // )
- // var opts []findopt.Find
- // opts = append(opts, findopt.Sort(bson.NewDocument(bson.EC.Int32("_id", -1))))
- // opts = append(opts, findopt.Limit(nPerPage))
- // cursor, _ := collection.Find(context.Background(), filter, opts...)
- // var lastValue *bson.Value
- // var results []bson.Document
- // for cursor.Next(context.Background()) {
- // elem := bson.NewDocument()
- // err := cursor.Decode(elem)
- // if err != nil {
- // return results, lastValue, err
- // }
- // results = append(results, *elem)
- // lastValue = elem.Lookup("_id")
- // }
- // return results, lastValue, nil
- // }
- // func (t *Mongo) Patch(f *Filter) *errs.Error {
- // var (
- // entityinterface EntityInterface
- // col *mongo.Collection
- // entity interface{}
- // ok bool
- // session *mgo.Session
- // err error
- // x *bson.M
- // )
- // if session, err = t.GetClient(f.DB); err == nil {
- // if !f.Id.IsZero() {
- // f.Query = &bson.M{"_id": f.Id}
- // } else if f.Query == nil {
- // err = fmt.Errorf("Query not defined!")
- // goto ErrorPatch
- // }
- // defer session.Close()
- // if entityinterface, ok = f.Entity.(EntityInterface); ok {
- // entity = entityinterface.Update()
- // x = entity.(*bson.M)
- // // delete(*x, "$set")
- // } else {
- // entity = bson.M{"$set": f.Entity}
- // }
- // col = session.DB(f.DB).C(f.Collection)
- // // entity["$set"]
- // spew.Dump(entity)
- // _, err = col.Upsert(f.Query, entity)
- // }
- // ErrorPatch:
- // if err != nil {
- // return Error(ERR_PERSIST, err.Error())
- // }
- // return nil
- // }
- // func (t *Mongo) Upsert(f *Filter) *errs.Error {
- // var (
- // entityinterface EntityInterface
- // col *mongo.Collection
- // entity interface{}
- // ok bool
- // )
- // session, err := t.GetClient(f.DB)
- // if err == nil {
- // if !f.Id.IsZero() {
- // f.Query = &bson.M{"_id": f.Id}
- // } else if f.Query == nil {
- // err = fmt.Errorf("Query not defined!")
- // goto ErrorUp
- // }
- // defer session.Close()
- // col = session.DB(f.DB).C(f.Collection)
- // // update = bson.M{"$set": f.Entity}
- // // if data, ok = f.Entity.Push(); ok {
- // // update["$push"] = data
- // // }
- // // if data, ok = f.Entity.Pull(); ok {
- // // update["$pull"] = data
- // // }
- // // spew.Dump(f.Entity)
- // if entityinterface, ok = f.Entity.(EntityInterface); ok {
- // // fmt.Println("Implement interface")
- // entity = entityinterface.Update()
- // } else {
- // entity = f.Entity
- // }
- // // spew.Dump(entity)
- // // _, err = col.Upsert(f.Query, entity)
- // err = col.Update(f.Query, entity)
- // }
- // ErrorUp:
- // if err != nil {
- // return Error(ERR_PERSIST, err.Error())
- // }
- // return nil
- // }
- //-----------------------------------------------------------------------
- // func (t *Mongo) Find(f *Filter, one bool) (*errs.Error, int) {
- // var cursor string
- // pageToken := &f.PageToken
- // session, err := t.GetClient(f.DB)
- // if err == nil {
- // defer session.Close()
- // if f.Query == nil {
- // if one {
- // if !f.Id.IsZero() {
- // f.Query = &bson.M{"_id": f.Id}
- // } else {
- // return Error(ERR_INVALID_PARAM_VALUE, "Param id not valid."), 0
- // }
- // } else if f.Query == nil {
- // f.Query = &bson.M{}
- // }
- // }
- // query := minquery.New(session.DB(f.DB), f.Collection, f.Query)
- // // Se tem um token de paginacao
- // hasToken := pageToken.HasToken()
- // if hasToken {
- // fmt.Println("consultando com token", pageToken.Cursor)
- // query = query.Cursor(pageToken.Cursor)
- // }
- // // cursorFields := []string{"_id"}
- // cursorFields := []string{}
- // if len(f.Sort) > 0 {
- // query.Sort(f.Sort...)
- // for _, key := range f.Sort {
- // if !strings.Contains(key, ".") {
- // cursorFields = append(cursorFields, key)
- // }
- // }
- // } else {
- // cursorFields = append(cursorFields, "_id")
- // }
- // // Seleciona os campos se forem especificados
- // if f.Fields != nil {
- // query.Select(f.Fields)
- // }
- // // Determina o numero de itens a ser retornado
- // if f.MaxResults > 0 {
- // query.Limit(f.MaxResults)
- // }
- // if one {
- // err = query.One(f.Entity)
- // pageToken.Count = 1 // Filter one
- // } else {
- // // spew.Dump(f.Entity, cursorFields)
- // if cursor, err = query.All(f.Entity, cursorFields...); err != nil {
- // goto ErroFind
- // }
- // // Numero total de documentos
- // // Se tem um token de paginacao o valor total esta no token
- // // Caso contrario consulta no banco
- // if !hasToken {
- // c := session.DB(f.DB).C(f.Collection)
- // if pageToken.Count, err = c.Find(f.Query).Select(&bson.M{"_id": 1}).Count(); err != nil {
- // goto ErroFind
- // }
- // }
- // // if ()
- // fmt.Println("Cursor return", cursor, "-")
- // pageToken.NewCursor = cursor
- // }
- // }
- // ErroFind:
- // if err != nil {
- // return Error(ERR_PERSIST, err.Error()), 0
- // }
- // return nil, pageToken.Count
- // }
- // func (t *Mongo) FindOne(f *Filter) (*errs.Error, int) {
- // return t.Find(f, true)
- // }
- // func (t *Mongo) FindAll(f *Filter) (*errs.Error, int) {
- // return t.Find(f, false)
- // }
- // func (t *Mongo) Count(f *Filter) (*errs.Error, int) {
- // session, err := t.GetClient(f.DB)
- // if err == nil {
- // defer session.Close()
- // if f.Query == nil {
- // f.Query = &bson.M{}
- // }
- // query := session.DB(f.DB).C(f.Collection).Find(f.Query)
- // // Seleciona os campos se forem especificados
- // f.PageToken.Count, err = query.Select(&bson.M{"_id": 1}).Count()
- // }
- // if err != nil {
- // return Error(ERR_PERSIST, err.Error()), 0
- // }
- // return nil, f.PageToken.Count
- // }
- // func (t *Mongo) Update(f *Filter) *errs.Error {
- // var (
- // entityinterface EntityInterface
- // entity interface{}
- // )
- // one := false
- // ok := false
- // session, err := t.GetClient(f.DB)
- // if err == nil {
- // defer session.Close()
- // if !f.Id.IsZero() {
- // one = true
- // f.Query = &bson.M{"_id": f.Id}
- // } else if f.Query == nil {
- // err = fmt.Errorf("Query not defined!")
- // }
- // if entityinterface, ok = f.Entity.(EntityInterface); ok {
- // entity = entityinterface.Update()
- // } else {
- // entity = f.Entity
- // }
- // col := session.DB(f.DB).C(f.Collection)
- // if one {
- // err = col.Update(f.Query, entity)
- // } else {
- // _, err = col.UpdateAll(f.Query, entity)
- // }
- // }
- // if err != nil {
- // return Error(ERR_PERSIST, err.Error())
- // }
- // return nil
- // }
- //-----------------------------------------------------------------------
- // func (t *Mongo) Aggregation(f *Filter, q []bson.M, one bool) *errs.Error {
- // session, err := t.GetClient(f.DB)
- // if err == nil {
- // defer session.Close()
- // pipe := session.DB(f.DB).C(f.Collection).Pipe(q)
- // if one {
- // err = pipe.One(&f.Entity)
- // } else {
- // err = pipe.All(&f.Entity)
- // }
- // }
- // if err != nil {
- // return Error(ERR_PERSIST, err.Error())
- // }
- // return nil
- // }
- // all := true
- // session, err := t.GetClient(f.DB)
- // if err == nil {
- // defer session.Close()
- // if !f.Id.IsZero() {
- // all = false
- // f.Query = &bson.M{"_id": f.Id}
- // } else if f.Query == nil {
- // err = fmt.Errorf("Query not defined!")
- // }
- // C := session.DB(f.DB).C(f.Collection)
- // if all {
- // _, err = C.RemoveAll(f.Query)
- // } else {
- // err = C.Remove(f.Query)
- // }
- // }
- // if err != nil {
- // return Error(ERR_PERSIST, err.Error())
- // }
- // return nil
- // VERIFICAR A NECESSIDADE E CORRIGIR O ERRO
- // func (t *Mongo) GetArrayById(f *Filter, ids []primitive.ObjectID) error {
- // session, err := t.GetClient(f.DB)
- // if err != nil {
- // return err
- // }
- // defer session.Close()
- // q := bson.M{"_id": bson.M{"$in": ids}}
- // err = session.DB(f.DB).C(f.Collection).Find(q).One(f.Entity)
- // return err
- // }
- // func (t *Mongo) GetEmbedFromArray(f *Filter, embed string, id primitive.ObjectID, sid primitive.ObjectID) (errs error) {
- // session, err := t.GetClient(f.DB)
- // if err != nil {
- // return err
- // }
- // defer session.Close()
- // field := "$" + embed
- // match := bson.M{"_id": id}
- // match[embed] = bson.M{"$exists": true}
- // aggregations := []bson.M{
- // bson.M{"$unwind": field},
- // bson.M{"$match": match},
- // bson.M{"$replaceRoot": bson.M{"newRoot": field}},
- // bson.M{"$match": bson.M{"_id": sid}},
- // }
- // C := session.DB(f.DB).C(f.Collection)
- // return C.Pipe(aggregations).One(&f.Entity)
- // }
- // func (t *Mongo) UpdateEmbedFromArray(f *Filter, embed string, id primitive.ObjectID, sid primitive.ObjectID) error {
- // session, err := t.GetClient(f.DB)
- // if err != nil {
- // return err
- // }
- // defer session.Close()
- // col := session.DB(f.DB).C(f.Collection)
- // //Define o elemento que sera atualizado
- // element := bson.M{}
- // element[embed+".$"] = &f.Entity
- // //Define o seletor do elemento que sera atualizado
- // selector := bson.M{"_id": id}
- // selector[embed+"._id"] = sid
- // return col.Update(selector, bson.M{"$set": element})
- // }
- // func (t *Mongo) AddEmbedFromArray(f *Filter, embed string, id primitive.ObjectID) error {
- // session, errs := t.GetClient(f.DB)
- // if errs != nil {
- // return errs
- // }
- // defer session.Close()
- // col := session.DB(f.DB).C(f.Collection)
- // //Define o elemento que sera atualizado
- // element := bson.M{}
- // element[embed] = &f.Entity
- // //Define o seletor do elemento que sera atualizado
- // selector := bson.M{"_id": id}
- // return col.Update(selector, bson.M{"$push": element})
- // }
- // 0000000000000000000000000000000000000000000000000000000000000000
- // func (t *Mongo) NewTransaction(dbname string) (*Transaction, error) {
- // session, e := t.GetClient(dbname)
- // if e != nil {
- // return nil, e
- // }
- // collection := session.DB(dbname).C("txns")
- // return &Transaction{R: txn.NewRunner(collection)}, nil
- // }
- // Transactions
- // type Transaction struct {
- // R *txn.Runner
- // Ops []txn.Op
- // }
- // func (t *Transaction) Insert(collection string, id primitive.ObjectID, entity interface{}) *Transaction {
- // t.Ops = append(t.Ops, txn.Op{
- // C: collection,
- // Id: id,
- // Insert: entity,
- // })
- // return t
- // }
- // func (t *Transaction) Update(collection string, id primitive.ObjectID, assert *bson.M, entity interface{}) *Transaction {
- // op := txn.Op{
- // C: collection,
- // Id: id,
- // Update: entity,
- // }
- // if assert != nil {
- // op.Assert = assert
- // }
- // t.Ops = append(t.Ops, op)
- // return t
- // }
- // func (t *Transaction) Remove(collection string, id primitive.ObjectID) *Transaction {
- // t.Ops = append(t.Ops, txn.Op{
- // C: collection,
- // Id: id,
- // Remove: true,
- // })
- // return t
- // }
- // func (t *Transaction) Run() error {
- // return t.R.Run(t.Ops, primitive.NewObjectID(), nil)
- // }
- // func (t *Mongo) Find(f *Filter, one bool) (*errs.Error, int) {
- // session, err := t.GetClient()
- // if err == nil {
- // defer session.Close()
- // if !f.Id.IsZero() {
- // f.Query = &bson.M{"_id": f.Id}
- // } else if f.Query == nil {
- // f.Query = &bson.M{}
- // }
- // pageToken := &f.PageToken
- // aggregations := []*bson.M{}
- // // Se tem um token de paginacao
- // hasToken := pageToken.HasToken()
- // if hasToken {
- // fmt.Println("consultando com token", pageToken.CurrentID)
- // // {$or:
- // // [
- // // {$and :
- // // [
- // // {<sort key>:{$gte: <last sort key value of previous page>}},
- // // {"_id" : {$gt : <last result id of previous page>}}
- // // ]
- // // },
- // // ou
- // // {<sort key> :{$gt: <last sort key value>}}
- // // ]
- // // }.
- // // f.Query = &bson.M{"$and": []bson.M{
- // // *f.Query,
- // // bson.M{"_id": bson.M{"$gt": f.NextPageToken}},
- // // }}
- // f.Query = &bson.M{"_id": bson.M{
- // // "$gt": primitive.ObjectIDHex(pageToken.CurrentID),
- // "$gt": pageToken.CurrentID,
- // }}
- // } else {
- // }
- // // Adiciona o primeiro estagio da agregacao
- // aggregations = append(aggregations, &bson.M{"$match": f.Query})
- // if len(f.Sort) > 0 {
- // f.Sort = append(f.Sort, "_id")
- // aggregations = append(aggregations, MgoSortBson(f.Sort))
- // // query.Sort(f.Sort...)
- // }
- // // aggregations = append(aggregations, &bson.M{
- // // "$addFields": bson.M{"position":},
- // // })
- // // Seleciona os campos se forem especificados
- // if f.Fields != nil {
- // // aggregations = append(aggregations, bson.M{"$limit": f.MaxResults})
- // }
- // // countQuery := session.DB(f.DB).C(f.Collection).Pipe(aggregations)
- // // Determina o numero de itens a ser retornado
- // if f.MaxResults > 0 {
- // aggregations = append(aggregations, &bson.M{"$limit": f.MaxResults})
- // }
- // spew.Dump(aggregations)
- // // query := session.DB(f.DB).C(f.Collection).Find(f.Query)
- // collection := session.DB(f.DB).C(f.Collection)
- // query := collection.Pipe(aggregations)
- // if one {
- // err = query.One(f.Entity)
- // f.Count = 1 // Filter one
- // } else {
- // err = query.All(f.Entity)
- // // Numero total de documentos
- // // Se tem um token de paginacao o valor total esta no token
- // // Caso contrario consulta no banco
- // if hasToken {
- // f.Count = pageToken.Count
- // } else {
- // f.Count, _ = collection.Find(f.Query).Select(&bson.M{"_id": 1}).Count()
- // }
- // }
- // }
- // if err != nil {
- // return Error(ERR_PERSIST, err.Error()), 0
- // }
- // return nil, f.Count
- // }
- // v := reflect.ValueOf(f.Entity)
- // fmt.Println("UpdateCursorResponse")
- // // spew.Dump(f.PageToken)
- // // fmt.Println(v.Kind())
- // if v.Kind() == reflect.Ptr {
- // // Atualiza v para o elemento apontado
- // v = v.Elem()
- // if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
- // // Acessa o atributo ID da ultima entidade do array
- // field := v.Index(v.Len() - 1).Elem().FieldByName("ID")
- // // Converte o atributo ID para objectId
- // last := field.Interface().(primitive.ObjectID)
- // // Cria a consulta que verifica se existe outros registros alem do ultimo
- // filter := &Filter{
- // Collection: f.Collection,
- // Query: &bson.M{"_id": bson.M{
- // "$lt": last,
- // }},
- // }
- // // Se existirem elementos adiciona o nextTOKEN
- // if _, count := models.Count(filter); count > 0 {
- // // atualiza os valores do token
- // f.PageToken.StartID = last.Hex()
- // f.PageToken.Count = f.Count
- // resp.NextPageToken = f.PageToken.Encode()
- // }
- // }
- // }
- // func NewMongo() (*Mongo, error) {
- // // session, err := mgo.Dial(addrs)
- // // session, err := mgo.Dial("mongodb://localhost:27017")
- // session, err := mgo.Dial("mongodb://localhost:27017")
- // if err != nil {
- // return nil, err
- // }
- // session.SetMode(mgo.Monotonic, true)
- // // "addrs": "mongodb://localhost:27017",
- // // "user": "guest",
- // // "password": "welcome",
- // // "database": "financeiro"
- // m := &Mongo{
- // Session: session,
- // DataBase: "accounts",
- // Addrs: ,
- // // Config: cfg,
- // }
- // return m, err
- // }
|