mirror of
https://github.com/mainnika/mongox-go-driver.git
synced 2026-05-23 00:03:36 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 87708fee04 | |||
| 06f6f48f11 | |||
| 28be1f46b9 | |||
| 848703d56d | |||
| 8fcd764a8c | |||
| 50e947b203 | |||
| 73dc4974a2 | |||
| 08397650c6 | |||
| ee4bf46662 | |||
| 9fb3094b87 | |||
| b22b0f0919 | |||
| 951e5f5bef | |||
| b796d5ac3b |
@@ -3,6 +3,8 @@ module github.com/mainnika/mongox-go-driver/v2
|
|||||||
require (
|
require (
|
||||||
github.com/google/go-cmp v0.3.0 // indirect
|
github.com/google/go-cmp v0.3.0 // indirect
|
||||||
github.com/klauspost/compress v1.10.1 // indirect
|
github.com/klauspost/compress v1.10.1 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.1
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
github.com/xdg/stringprep v1.0.0 // indirect
|
github.com/xdg/stringprep v1.0.0 // indirect
|
||||||
|
|||||||
@@ -44,11 +44,17 @@ github.com/klauspost/compress v1.10.1 h1:a/QY0o9S6wCi0XhxaMX/QmusicNUqCqFugR6WKP
|
|||||||
github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
@@ -113,6 +119,7 @@ golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package base
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/modern-go/reflect2"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox"
|
"github.com/mainnika/mongox-go-driver/v2/mongox"
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetID returns source document id
|
// GetID returns source document id
|
||||||
@@ -63,7 +63,7 @@ func getObjectOrPanic(source mongox.JSONBased) (id primitive.D) {
|
|||||||
func getInterfaceOrPanic(source mongox.InterfaceBased) (id interface{}) {
|
func getInterfaceOrPanic(source mongox.InterfaceBased) (id interface{}) {
|
||||||
|
|
||||||
id = source.GetID()
|
id = source.GetID()
|
||||||
if !utils.IsNil(id) {
|
if !reflect2.IsNil(id) {
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox/query"
|
|
||||||
)
|
|
||||||
|
|
||||||
func onDecode(ctx context.Context, iter interface{}, callbacks ...query.OnDecode) (err error) {
|
|
||||||
|
|
||||||
for _, cb := range callbacks {
|
|
||||||
err = cb(ctx, iter)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -13,11 +13,14 @@ func (d *Database) Count(target interface{}, filters ...interface{}) (result int
|
|||||||
collection := d.GetCollectionOf(target)
|
collection := d.GetCollectionOf(target)
|
||||||
opts := options.Count()
|
opts := options.Count()
|
||||||
composed := query.Compose(filters...)
|
composed := query.Compose(filters...)
|
||||||
|
ctx := query.WithContext(d.Context(), composed)
|
||||||
|
|
||||||
opts.Limit = composed.Limiter()
|
opts.Limit = composed.Limiter()
|
||||||
opts.Skip = composed.Skipper()
|
opts.Skip = composed.Skipper()
|
||||||
|
|
||||||
result, err = collection.CountDocuments(d.Context(), composed.M(), opts)
|
result, err = collection.CountDocuments(ctx, composed.M(), opts)
|
||||||
|
|
||||||
|
_ = composed.OnClose().Invoke(ctx, target)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,11 @@ import (
|
|||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox/base"
|
"github.com/mainnika/mongox-go-driver/v2/mongox/base"
|
||||||
|
"github.com/mainnika/mongox-go-driver/v2/mongox/query"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteArray removes documents list from a database by their ids
|
// DeleteArray removes documents list from a database by their ids
|
||||||
func (d *Database) DeleteArray(target interface{}) (err error) {
|
func (d *Database) DeleteArray(target interface{}, filters ...interface{}) (err error) {
|
||||||
|
|
||||||
targetV := reflect.ValueOf(target)
|
targetV := reflect.ValueOf(target)
|
||||||
targetT := targetV.Type()
|
targetT := targetV.Type()
|
||||||
@@ -37,6 +38,8 @@ func (d *Database) DeleteArray(target interface{}) (err error) {
|
|||||||
collection := d.GetCollectionOf(zeroElem.Interface())
|
collection := d.GetCollectionOf(zeroElem.Interface())
|
||||||
opts := options.Delete()
|
opts := options.Delete()
|
||||||
ids := primitive.A{}
|
ids := primitive.A{}
|
||||||
|
composed := query.Compose(filters...)
|
||||||
|
ctx := query.WithContext(d.Context(), composed)
|
||||||
|
|
||||||
for i := 0; i < targetLen; i++ {
|
for i := 0; i < targetLen; i++ {
|
||||||
elem := targetSliceV.Index(i)
|
elem := targetSliceV.Index(i)
|
||||||
@@ -47,7 +50,11 @@ func (d *Database) DeleteArray(target interface{}) (err error) {
|
|||||||
return fmt.Errorf("can't delete zero elements")
|
return fmt.Errorf("can't delete zero elements")
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := collection.DeleteMany(d.Context(), primitive.M{"_id": primitive.M{"$in": ids}}, opts)
|
composed.And(primitive.M{"_id": primitive.M{"$in": ids}})
|
||||||
|
|
||||||
|
defer composed.OnClose().Invoke(ctx, target)
|
||||||
|
|
||||||
|
result, err := collection.DeleteMany(ctx, composed.M(), opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/modern-go/reflect2"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox/base"
|
"github.com/mainnika/mongox-go-driver/v2/mongox/base"
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox/query"
|
"github.com/mainnika/mongox-go-driver/v2/mongox/query"
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeleteOne removes a document from a database and then returns it into target
|
// DeleteOne removes a document from a database and then returns it into target
|
||||||
@@ -19,10 +19,11 @@ func (d *Database) DeleteOne(target interface{}, filters ...interface{}) (err er
|
|||||||
opts := &options.FindOneAndDeleteOptions{}
|
opts := &options.FindOneAndDeleteOptions{}
|
||||||
composed := query.Compose(filters...)
|
composed := query.Compose(filters...)
|
||||||
protected := base.GetProtection(target)
|
protected := base.GetProtection(target)
|
||||||
|
ctx := query.WithContext(d.Context(), composed)
|
||||||
|
|
||||||
opts.Sort = composed.Sorter()
|
opts.Sort = composed.Sorter()
|
||||||
|
|
||||||
if !utils.IsNil(target) {
|
if !reflect2.IsNil(target) {
|
||||||
composed.And(primitive.M{"_id": base.GetID(target)})
|
composed.And(primitive.M{"_id": base.GetID(target)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,12 +33,22 @@ func (d *Database) DeleteOne(target interface{}, filters ...interface{}) (err er
|
|||||||
protected.V = time.Now().Unix()
|
protected.V = time.Now().Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
result := collection.FindOneAndDelete(d.Context(), composed.M(), opts)
|
defer composed.OnClose().Invoke(ctx, target)
|
||||||
|
|
||||||
|
result := collection.FindOneAndDelete(ctx, composed.M(), opts)
|
||||||
if result.Err() != nil {
|
if result.Err() != nil {
|
||||||
return fmt.Errorf("can't create find one and delete result: %w", result.Err())
|
return fmt.Errorf("can't create find one and delete result: %w", result.Err())
|
||||||
}
|
}
|
||||||
|
|
||||||
err = result.Decode(target)
|
err = result.Decode(target)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = composed.OnDecode().Invoke(ctx, target)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
|
|||||||
composed := query.Compose(filters...)
|
composed := query.Compose(filters...)
|
||||||
zeroElem := reflect.Zero(targetSliceElemT)
|
zeroElem := reflect.Zero(targetSliceElemT)
|
||||||
hasPreloader, _ := composed.Preloader()
|
hasPreloader, _ := composed.Preloader()
|
||||||
|
ctx := query.WithContext(d.Context(), composed)
|
||||||
|
|
||||||
var result *mongox.Cursor
|
var result *mongox.Cursor
|
||||||
var i int
|
var i int
|
||||||
@@ -48,7 +49,9 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i = 0; result.Next(d.Context()); {
|
defer composed.OnClose().Invoke(ctx, target)
|
||||||
|
|
||||||
|
for i = 0; result.Next(ctx); {
|
||||||
|
|
||||||
var elem interface{}
|
var elem interface{}
|
||||||
|
|
||||||
@@ -65,13 +68,13 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
|
|||||||
err = result.Decode(elem)
|
err = result.Decode(elem)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = result.Close(d.Context())
|
_ = result.Close(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = onDecode(d.ctx, elem, composed.OnDecode()...)
|
err = composed.OnDecode().Invoke(ctx, elem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = result.Close(d.Context())
|
_ = result.Close(ctx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,5 +84,5 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
|
|||||||
targetSliceV = targetSliceV.Slice(0, i)
|
targetSliceV = targetSliceV.Slice(0, i)
|
||||||
targetV.Elem().Set(targetSliceV)
|
targetV.Elem().Set(targetSliceV)
|
||||||
|
|
||||||
return result.Close(d.Context())
|
return result.Close(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ func (d *Database) LoadOne(target interface{}, filters ...interface{}) (err erro
|
|||||||
|
|
||||||
composed := query.Compose(append(filters, query.Limit(1))...)
|
composed := query.Compose(append(filters, query.Limit(1))...)
|
||||||
hasPreloader, _ := composed.Preloader()
|
hasPreloader, _ := composed.Preloader()
|
||||||
|
ctx := query.WithContext(d.Context(), composed)
|
||||||
|
|
||||||
var result *mongox.Cursor
|
var result *mongox.Cursor
|
||||||
|
|
||||||
@@ -25,7 +26,9 @@ func (d *Database) LoadOne(target interface{}, filters ...interface{}) (err erro
|
|||||||
return fmt.Errorf("can't create find result: %w", err)
|
return fmt.Errorf("can't create find result: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hasNext := result.Next(d.Context())
|
defer composed.OnClose().Invoke(ctx, target)
|
||||||
|
|
||||||
|
hasNext := result.Next(ctx)
|
||||||
if result.Err() != nil {
|
if result.Err() != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -40,7 +43,7 @@ func (d *Database) LoadOne(target interface{}, filters ...interface{}) (err erro
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = onDecode(d.ctx, target, composed.OnDecode()...)
|
err = composed.OnDecode().Invoke(ctx, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ func (d *Database) LoadStream(target interface{}, filters ...interface{}) (loade
|
|||||||
|
|
||||||
composed := query.Compose(filters...)
|
composed := query.Compose(filters...)
|
||||||
hasPreloader, _ := composed.Preloader()
|
hasPreloader, _ := composed.Preloader()
|
||||||
|
ctx := query.WithContext(d.Context(), composed)
|
||||||
|
|
||||||
if hasPreloader {
|
if hasPreloader {
|
||||||
cursor, err = d.createAggregateLoad(target, composed)
|
cursor, err = d.createAggregateLoad(target, composed)
|
||||||
@@ -25,7 +26,7 @@ func (d *Database) LoadStream(target interface{}, filters ...interface{}) (loade
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loader = &StreamLoader{cur: cursor, ctx: d.Context(), target: target, query: composed}
|
loader = &StreamLoader{cur: cursor, ctx: ctx, target: target, query: composed}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// SaveOne saves a single source document to the database
|
// SaveOne saves a single source document to the database
|
||||||
func (d *Database) SaveOne(source interface{}) (err error) {
|
func (d *Database) SaveOne(source interface{}, filters ...interface{}) (err error) {
|
||||||
|
|
||||||
collection := d.GetCollectionOf(source)
|
collection := d.GetCollectionOf(source)
|
||||||
opts := options.FindOneAndReplace()
|
opts := options.FindOneAndReplace()
|
||||||
id := base.GetID(source)
|
id := base.GetID(source)
|
||||||
protected := base.GetProtection(source)
|
protected := base.GetProtection(source)
|
||||||
composed := query.Compose(bson.M{"_id": id})
|
composed := query.Compose(filters...)
|
||||||
|
ctx := query.WithContext(d.Context(), composed)
|
||||||
|
|
||||||
|
composed.And(bson.M{"_id": id})
|
||||||
|
|
||||||
opts.SetUpsert(true)
|
opts.SetUpsert(true)
|
||||||
opts.SetReturnDocument(options.After)
|
opts.SetReturnDocument(options.After)
|
||||||
@@ -29,10 +32,22 @@ func (d *Database) SaveOne(source interface{}) (err error) {
|
|||||||
protected.V = time.Now().Unix()
|
protected.V = time.Now().Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
result := collection.FindOneAndReplace(d.Context(), composed.M(), source, opts)
|
defer composed.OnClose().Invoke(ctx, source)
|
||||||
|
|
||||||
|
result := collection.FindOneAndReplace(ctx, composed.M(), source, opts)
|
||||||
if result.Err() != nil {
|
if result.Err() != nil {
|
||||||
return result.Err()
|
return result.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.Decode(source)
|
err = result.Decode(source)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = composed.OnDecode().Invoke(ctx, source)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func (l *StreamLoader) Decode() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = onDecode(l.ctx, l.target, l.query.OnDecode()...)
|
err = l.query.OnDecode().Invoke(l.ctx, l.target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -72,6 +72,9 @@ func (l *StreamLoader) Cursor() (cursor *mongox.Cursor) {
|
|||||||
|
|
||||||
// Close cursor
|
// Close cursor
|
||||||
func (l *StreamLoader) Close() (err error) {
|
func (l *StreamLoader) Close() (err error) {
|
||||||
|
|
||||||
|
_ = l.query.OnClose().Invoke(l.ctx, l.target)
|
||||||
|
|
||||||
return l.cur.Close(l.ctx)
|
return l.cur.Close(l.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -22,12 +22,12 @@ type Database interface {
|
|||||||
New(ctx context.Context) (db Database)
|
New(ctx context.Context) (db Database)
|
||||||
GetCollectionOf(document interface{}) (collection *Collection)
|
GetCollectionOf(document interface{}) (collection *Collection)
|
||||||
Count(target interface{}, filters ...interface{}) (count int64, err error)
|
Count(target interface{}, filters ...interface{}) (count int64, err error)
|
||||||
DeleteArray(target interface{}) (err error)
|
DeleteArray(target interface{}, filters ...interface{}) (err error)
|
||||||
DeleteOne(target interface{}, filters ...interface{}) (err error)
|
DeleteOne(target interface{}, filters ...interface{}) (err error)
|
||||||
LoadArray(target interface{}, filters ...interface{}) (err error)
|
LoadArray(target interface{}, filters ...interface{}) (err error)
|
||||||
LoadOne(target interface{}, filters ...interface{}) (err error)
|
LoadOne(target interface{}, filters ...interface{}) (err error)
|
||||||
LoadStream(target interface{}, filters ...interface{}) (loader StreamLoader, err error)
|
LoadStream(target interface{}, filters ...interface{}) (loader StreamLoader, err error)
|
||||||
SaveOne(source interface{}) (err error)
|
SaveOne(source interface{}, filters ...interface{}) (err error)
|
||||||
IndexEnsure(cfg interface{}, document interface{}) (err error)
|
IndexEnsure(cfg interface{}, document interface{}) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,4 +4,23 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OnDecode func(ctx context.Context, iter interface{}) (err error)
|
type Callback func(ctx context.Context, iter interface{}) (err error)
|
||||||
|
type Callbacks []Callback
|
||||||
|
|
||||||
|
type (
|
||||||
|
OnDecode Callback
|
||||||
|
OnClose Callback
|
||||||
|
)
|
||||||
|
|
||||||
|
// Invoke callbacks sequence
|
||||||
|
func (c Callbacks) Invoke(ctx context.Context, iter interface{}) (err error) {
|
||||||
|
|
||||||
|
for _, cb := range c {
|
||||||
|
err = cb(ctx, iter)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package query
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/modern-go/reflect2"
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox/base/protection"
|
"github.com/mainnika/mongox-go-driver/v2/mongox/base/protection"
|
||||||
"github.com/mainnika/mongox-go-driver/v2/mongox/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Compose is a function to compose filters into a single query
|
// Compose is a function to compose filters into a single query
|
||||||
@@ -27,7 +27,7 @@ func Compose(filters ...interface{}) (query *Query) {
|
|||||||
// Push applies single filter to a query
|
// Push applies single filter to a query
|
||||||
func Push(q *Query, f interface{}) (ok bool) {
|
func Push(q *Query, f interface{}) (ok bool) {
|
||||||
|
|
||||||
if utils.IsNil(f) {
|
if reflect2.IsNil(f) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,9 +129,14 @@ func applyCallbacks(q *Query, f interface{}) (ok bool) {
|
|||||||
|
|
||||||
switch cb := f.(type) {
|
switch cb := f.(type) {
|
||||||
case OnDecode:
|
case OnDecode:
|
||||||
q.ondecode = append(q.ondecode, cb)
|
q.ondecode = append(q.ondecode, Callback(cb))
|
||||||
ok = true
|
case OnClose:
|
||||||
|
q.onclose = append(q.onclose, Callback(cb))
|
||||||
|
default:
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ok = true
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package query
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ctxQueryKey struct{}
|
||||||
|
|
||||||
|
// GetFromContext function extracts the request data from context
|
||||||
|
func GetFromContext(ctx context.Context) (q *Query, ok bool) {
|
||||||
|
q, ok = ctx.Value(ctxQueryKey{}).(*Query)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext function creates the new context with request data
|
||||||
|
func WithContext(ctx context.Context, q *Query) (withQuery context.Context) {
|
||||||
|
withQuery = context.WithValue(ctx, ctxQueryKey{}, q)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -11,7 +11,8 @@ type Query struct {
|
|||||||
sorter Sorter
|
sorter Sorter
|
||||||
skipper Skipper
|
skipper Skipper
|
||||||
preloader Preloader
|
preloader Preloader
|
||||||
ondecode []OnDecode
|
ondecode Callbacks
|
||||||
|
onclose Callbacks
|
||||||
}
|
}
|
||||||
|
|
||||||
// And function pushes the elem query to the $and array of the query
|
// And function pushes the elem query to the $and array of the query
|
||||||
@@ -77,10 +78,14 @@ func (q *Query) Preloader() (ok bool, preloads []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OnDecode callback is called after the mongo decode function
|
// OnDecode callback is called after the mongo decode function
|
||||||
func (q *Query) OnDecode() (callbacks []OnDecode) {
|
func (q *Query) OnDecode() (callbacks Callbacks) {
|
||||||
return q.ondecode
|
return q.ondecode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *Query) OnClose() (callbacks Callbacks) {
|
||||||
|
return q.onclose
|
||||||
|
}
|
||||||
|
|
||||||
// Empty checks the query for any content
|
// Empty checks the query for any content
|
||||||
func (q *Query) Empty() (isEmpty bool) {
|
func (q *Query) Empty() (isEmpty bool) {
|
||||||
return len(q.m) == 0
|
return len(q.m) == 0
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsNil function evaluates the interface value to nil
|
|
||||||
func IsNil(i interface{}) (isNil bool) {
|
|
||||||
|
|
||||||
type iface struct {
|
|
||||||
_ unsafe.Pointer
|
|
||||||
ptr unsafe.Pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
unpacked := (*iface)(unsafe.Pointer(&i))
|
|
||||||
if unpacked.ptr == nil {
|
|
||||||
isNil = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
isNil = *(*unsafe.Pointer)(unpacked.ptr) == nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIsNil(t *testing.T) {
|
|
||||||
|
|
||||||
testvalues := []struct {
|
|
||||||
i interface{}
|
|
||||||
isnil bool
|
|
||||||
}{
|
|
||||||
{nil, true},
|
|
||||||
{(*string)(nil), true},
|
|
||||||
{([]string)(nil), true},
|
|
||||||
{(map[string]string)(nil), true},
|
|
||||||
{(func() bool)(nil), true},
|
|
||||||
{(chan func() bool)(nil), true},
|
|
||||||
{"", true},
|
|
||||||
{0, true},
|
|
||||||
{append(([]string)(nil), ""), false},
|
|
||||||
{[]string{}, false},
|
|
||||||
{1, false},
|
|
||||||
{"1", false},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range testvalues {
|
|
||||||
assert.Equal(t, tt.isnil, IsNil(tt.i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user