mirror of
https://github.com/mainnika/mongox-go-driver.git
synced 2026-05-23 00:03:36 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e8e65d03e | |||
| 8d6a318bb2 | |||
| e52b1bcc8a | |||
| 04382db4cd | |||
| 80a5c864c5 | |||
| e087825026 | |||
| 8cc57cc82f | |||
| 18d9f9bed3 | |||
| 0bc4e62d80 |
@@ -5,7 +5,7 @@ go 1.13
|
|||||||
require (
|
require (
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.1
|
github.com/modern-go/reflect2 v1.0.1
|
||||||
github.com/stretchr/testify v1.6.1
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/valyala/bytebufferpool v1.0.0
|
github.com/valyala/bytebufferpool v1.0.0
|
||||||
go.mongodb.org/mongo-driver v1.4.3
|
go.mongodb.org/mongo-driver v1.4.6
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -75,11 +75,13 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
|||||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
@@ -88,8 +90,8 @@ github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV
|
|||||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||||
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo=
|
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo=
|
||||||
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||||
go.mongodb.org/mongo-driver v1.4.3 h1:moga+uhicpVshTyaqY9L23E6QqwcHRUv1sqyOsoyOO8=
|
go.mongodb.org/mongo-driver v1.4.6 h1:rh7GdYmDrb8AQSkF8yteAus8qYOgOASWDOv1BWqBXkU=
|
||||||
go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
|
go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Reset function creates new zero object for the target pointer
|
// Reset function creates new zero object for the target pointer
|
||||||
func Reset(target interface{}) {
|
func Reset(target interface{}) (created bool) {
|
||||||
|
|
||||||
type resetter interface {
|
type resetter interface {
|
||||||
Reset()
|
Reset()
|
||||||
@@ -15,7 +15,7 @@ func Reset(target interface{}) {
|
|||||||
resettable, canReset := target.(resetter)
|
resettable, canReset := target.(resetter)
|
||||||
if canReset {
|
if canReset {
|
||||||
resettable.Reset()
|
resettable.Reset()
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
v := reflect.ValueOf(target)
|
v := reflect.ValueOf(target)
|
||||||
@@ -27,4 +27,6 @@ func Reset(target interface{}) {
|
|||||||
zero := reflect.Zero(t)
|
zero := reflect.Zero(t)
|
||||||
|
|
||||||
v.Elem().Set(zero)
|
v.Elem().Set(zero)
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,8 +126,12 @@ func (d *Database) createAggregateLoad(target interface{}, composed *query.Query
|
|||||||
pipeline = append(pipeline, primitive.M{"$limit": *composed.Limiter()})
|
pipeline = append(pipeline, primitive.M{"$limit": *composed.Limiter()})
|
||||||
}
|
}
|
||||||
|
|
||||||
el := reflect.ValueOf(target).Elem()
|
el := reflect.ValueOf(target)
|
||||||
elType := el.Type()
|
elType := el.Type()
|
||||||
|
if elType.Kind() == reflect.Ptr {
|
||||||
|
elType = elType.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
numField := elType.NumField()
|
numField := elType.NumField()
|
||||||
preloads, _ := composed.Preloader()
|
preloads, _ := composed.Preloader()
|
||||||
|
|
||||||
@@ -191,17 +195,20 @@ func (d *Database) createAggregateLoad(target interface{}, composed *query.Query
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
isSlice := el.Field(i).Kind() == reflect.Slice
|
field := elType.Field(i)
|
||||||
|
fieldType := field.Type
|
||||||
|
|
||||||
typ := el.Field(i).Type()
|
isSlice := fieldType.Kind() == reflect.Slice
|
||||||
if typ.Kind() == reflect.Slice {
|
if isSlice {
|
||||||
typ = typ.Elem()
|
fieldType = fieldType.Elem()
|
||||||
}
|
}
|
||||||
if typ.Kind() != reflect.Ptr {
|
|
||||||
|
isPtr := fieldType.Kind() != reflect.Ptr
|
||||||
|
if isPtr {
|
||||||
panic(fmt.Errorf("preload field should have ptr type"))
|
panic(fmt.Errorf("preload field should have ptr type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
lookupCollection := d.GetCollectionOf(reflect.Zero(typ).Interface())
|
lookupCollection := d.GetCollectionOf(reflect.Zero(fieldType).Interface())
|
||||||
lookupVars := primitive.M{"selector": "$" + localField}
|
lookupVars := primitive.M{"selector": "$" + localField}
|
||||||
lookupPipeline := primitive.A{
|
lookupPipeline := primitive.A{
|
||||||
primitive.M{"$match": primitive.M{"$expr": primitive.M{"$eq": primitive.A{"$" + foreignField, "$$selector"}}}},
|
primitive.M{"$match": primitive.M{"$expr": primitive.M{"$eq": primitive.A{"$" + foreignField, "$$selector"}}}},
|
||||||
|
|||||||
@@ -70,32 +70,45 @@ func (d *Database) LoadArray(target interface{}, filters ...interface{}) (err er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i = 0; result.Next(ctx); {
|
for i = 0; result.Next(ctx); i++ {
|
||||||
|
|
||||||
var elem interface{}
|
var elem interface{}
|
||||||
|
|
||||||
if targetSliceV.Len() == i {
|
if i == targetSliceV.Len() {
|
||||||
value := reflect.New(targetSliceElemT.Elem())
|
value := reflect.New(targetSliceElemT.Elem())
|
||||||
err = result.Decode(value.Interface())
|
|
||||||
elem = value.Interface()
|
elem = value.Interface()
|
||||||
if err == nil {
|
|
||||||
targetSliceV = reflect.Append(targetSliceV, value)
|
err = composed.OnCreate().Invoke(ctx, elem)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = result.Decode(elem)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
targetSliceV = reflect.Append(targetSliceV, value)
|
||||||
} else {
|
} else {
|
||||||
elem = targetSliceV.Index(i).Interface()
|
elem = targetSliceV.Index(i).Interface()
|
||||||
base.Reset(elem)
|
|
||||||
|
if created := base.Reset(elem); created {
|
||||||
|
err = composed.OnCreate().Invoke(ctx, elem)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = result.Decode(elem)
|
err = result.Decode(elem)
|
||||||
}
|
if err != nil {
|
||||||
if err != nil {
|
return
|
||||||
return
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = composed.OnDecode().Invoke(ctx, elem)
|
err = composed.OnDecode().Invoke(ctx, elem)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
targetSliceV = targetSliceV.Slice(0, i)
|
targetSliceV = targetSliceV.Slice(0, i)
|
||||||
|
|||||||
@@ -56,7 +56,12 @@ func (d *Database) LoadOne(target interface{}, filters ...interface{}) (err erro
|
|||||||
return mongox.ErrNoDocuments
|
return mongox.ErrNoDocuments
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Reset(target)
|
if created := base.Reset(target); created {
|
||||||
|
err = composed.OnCreate().Invoke(ctx, target)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err = result.Decode(target)
|
err = result.Decode(target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func (d *Database) LoadStream(target interface{}, filters ...interface{}) (loade
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loader = &StreamLoader{cur: cursor, ctx: ctx, target: target, query: composed}
|
loader = &StreamLoader{cur: cursor, ctx: ctx, query: composed}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,21 +10,20 @@ import (
|
|||||||
|
|
||||||
// StreamLoader is a controller for a database cursor
|
// StreamLoader is a controller for a database cursor
|
||||||
type StreamLoader struct {
|
type StreamLoader struct {
|
||||||
cur *mongox.Cursor
|
cur *mongox.Cursor
|
||||||
query *query.Query
|
query *query.Query
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
target interface{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeNext loads next documents to a target or returns an error
|
// DecodeNextMsg decodes the next document to an interface or returns an error
|
||||||
func (l *StreamLoader) DecodeNext() (err error) {
|
func (l *StreamLoader) DecodeNextMsg(i interface{}) (err error) {
|
||||||
|
|
||||||
err = l.Next()
|
err = l.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = l.Decode()
|
err = l.DecodeMsg(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -32,17 +31,22 @@ func (l *StreamLoader) DecodeNext() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode function decodes the current cursor document into the target
|
// DecodeMsg decodes the current cursor document into an interface
|
||||||
func (l *StreamLoader) Decode() (err error) {
|
func (l *StreamLoader) DecodeMsg(i interface{}) (err error) {
|
||||||
|
|
||||||
base.Reset(l.target)
|
if created := base.Reset(i); created {
|
||||||
|
err = l.query.OnDecode().Invoke(l.ctx, i)
|
||||||
err = l.cur.Decode(l.target)
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = l.query.OnDecode().Invoke(l.ctx, l.target)
|
err = l.cur.Decode(i)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = l.query.OnDecode().Invoke(l.ctx, i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -66,15 +70,16 @@ func (l *StreamLoader) Next() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cursor returns the underlying cursor
|
||||||
func (l *StreamLoader) Cursor() (cursor *mongox.Cursor) {
|
func (l *StreamLoader) Cursor() (cursor *mongox.Cursor) {
|
||||||
return l.cur
|
return l.cur
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close cursor
|
// Close stream loader and the underlying cursor
|
||||||
func (l *StreamLoader) Close() (err error) {
|
func (l *StreamLoader) Close() (err error) {
|
||||||
|
|
||||||
closerr := l.cur.Close(l.ctx)
|
closerr := l.cur.Close(l.ctx)
|
||||||
invokerr := l.query.OnClose().Invoke(l.ctx, l.target)
|
invokerr := l.query.OnClose().Invoke(l.ctx, nil)
|
||||||
|
|
||||||
if closerr != nil {
|
if closerr != nil {
|
||||||
err = closerr
|
err = closerr
|
||||||
@@ -89,6 +94,7 @@ func (l *StreamLoader) Close() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Err returns the last error
|
||||||
func (l *StreamLoader) Err() (err error) {
|
func (l *StreamLoader) Err() (err error) {
|
||||||
return l.cur.Err()
|
return l.cur.Err()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -35,8 +35,8 @@ type Database interface {
|
|||||||
// StreamLoader is a interface to control database cursor
|
// StreamLoader is a interface to control database cursor
|
||||||
type StreamLoader interface {
|
type StreamLoader interface {
|
||||||
Cursor() (cursor *Cursor)
|
Cursor() (cursor *Cursor)
|
||||||
DecodeNext() (err error)
|
DecodeNextMsg(i interface{}) (err error)
|
||||||
Decode() (err error)
|
DecodeMsg(i interface{}) (err error)
|
||||||
Next() (err error)
|
Next() (err error)
|
||||||
Close() (err error)
|
Close() (err error)
|
||||||
Err() (err error)
|
Err() (err error)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ type Query struct {
|
|||||||
updater Updater
|
updater Updater
|
||||||
ondecode Callbacks
|
ondecode Callbacks
|
||||||
onclose Callbacks
|
onclose Callbacks
|
||||||
|
oncreate 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
|
||||||
@@ -118,10 +119,16 @@ func (q *Query) OnDecode() (callbacks Callbacks) {
|
|||||||
return q.ondecode
|
return q.ondecode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnClose callback is called after the mongox ends a loading procedure
|
||||||
func (q *Query) OnClose() (callbacks Callbacks) {
|
func (q *Query) OnClose() (callbacks Callbacks) {
|
||||||
return q.onclose
|
return q.onclose
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnCreate callback is called if the mongox creates a new document instance during loading
|
||||||
|
func (q *Query) OnCreate() (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
|
||||||
|
|||||||
Reference in New Issue
Block a user