Compare commits

...

4 Commits

Author SHA1 Message Date
e7b2b040b2 v0.0.116 2023-05-05 18:22:15 +02:00
05d0f9e469 v0.0.115 2023-05-05 18:18:20 +02:00
ccd03e50c8 v0.0.114 2023-05-05 18:17:15 +02:00
1c77c2b8e8 v0.0.113 2023-05-05 18:05:58 +02:00
6 changed files with 91 additions and 1 deletions

View File

@@ -1274,7 +1274,7 @@ func TestMarshalSafeCollections(t *testing.T) {
} }
for i, tt := range tests { for i, tt := range tests {
b, err := MarshalSafeCollections(tt.in, true, true) b, err := MarshalSafeCollections(tt.in, true, true, nil)
if err != nil { if err != nil {
t.Errorf("test %d, unexpected failure: %v", i, err) t.Errorf("test %d, unexpected failure: %v", i, err)
} }

49
mongoext/pipeline.go Normal file
View File

@@ -0,0 +1,49 @@
package mongoext
import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
// FixTextSearchPipeline moves {$match:{$text:{$search}}} entries to the front of the pipeline (otherwise its an mongo error)
func FixTextSearchPipeline(pipeline mongo.Pipeline) mongo.Pipeline {
dget := func(v bson.D, k string) (bson.M, bool) {
for _, e := range v {
if e.Key == k {
if mv, ok := e.Value.(bson.M); ok {
return mv, true
}
}
}
return nil, false
}
mget := func(v bson.M, k string) (bson.M, bool) {
for ekey, eval := range v {
if ekey == k {
if mv, ok := eval.(bson.M); ok {
return mv, true
}
}
}
return nil, false
}
result := make([]bson.D, 0, len(pipeline))
for _, entry := range pipeline {
if v0, ok := dget(entry, "$match"); ok {
if v1, ok := mget(v0, "$text"); ok {
if _, ok := v1["$search"]; ok {
result = append([]bson.D{entry}, result...)
continue
}
}
}
result = append(result, entry)
}
return result
}

30
mongoext/projections.go Normal file
View File

@@ -0,0 +1,30 @@
package mongoext
import (
"go.mongodb.org/mongo-driver/bson"
"reflect"
"strings"
)
// ProjectionFromStruct automatically generated a mongodb projection for a struct
// This way you can pretty much always write
// `options.FindOne().SetProjection(mongoutils.ProjectionFromStruct(...your_model...))`
// to only get the data from mongodb that you will actually use in the later decode step
func ProjectionFromStruct(obj interface{}) bson.M {
v := reflect.ValueOf(obj)
t := v.Type()
result := bson.M{}
for i := 0; i < v.NumField(); i++ {
tag := t.Field(i).Tag.Get("bson")
if tag == "" {
continue
}
tag = strings.Split(tag, ",")[0]
result[tag] = 1
}
return result
}

View File

@@ -11,7 +11,10 @@ func CreateGoExtBsonRegistry() *bsoncodec.Registry {
rb := bsoncodec.NewRegistryBuilder() rb := bsoncodec.NewRegistryBuilder()
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.RFC3339Time{}), rfctime.RFC3339Time{}) rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.RFC3339Time{}), rfctime.RFC3339Time{})
rb.RegisterTypeDecoder(reflect.TypeOf(&rfctime.RFC3339Time{}), rfctime.RFC3339Time{})
rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.RFC3339NanoTime{}), rfctime.RFC3339NanoTime{}) rb.RegisterTypeDecoder(reflect.TypeOf(rfctime.RFC3339NanoTime{}), rfctime.RFC3339NanoTime{})
rb.RegisterTypeDecoder(reflect.TypeOf(&rfctime.RFC3339NanoTime{}), rfctime.RFC3339NanoTime{})
bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb) bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb)
bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb) bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb)

View File

@@ -71,6 +71,7 @@ func (t *RFC3339Time) UnmarshalText(data []byte) error {
func (t *RFC3339Time) UnmarshalBSONValue(bt bsontype.Type, data []byte) error { func (t *RFC3339Time) UnmarshalBSONValue(bt bsontype.Type, data []byte) error {
if bt == bsontype.Null { if bt == bsontype.Null {
// we can't set nil in UnmarshalBSONValue (so we use default(struct)) // we can't set nil in UnmarshalBSONValue (so we use default(struct))
// Use mongoext.CreateGoExtBsonRegistry if you need to unmarsh pointer values
// https://stackoverflow.com/questions/75167597 // https://stackoverflow.com/questions/75167597
// https://jira.mongodb.org/browse/GODRIVER-2252 // https://jira.mongodb.org/browse/GODRIVER-2252
*t = RFC3339Time{} *t = RFC3339Time{}

View File

@@ -71,6 +71,7 @@ func (t *RFC3339NanoTime) UnmarshalText(data []byte) error {
func (t *RFC3339NanoTime) UnmarshalBSONValue(bt bsontype.Type, data []byte) error { func (t *RFC3339NanoTime) UnmarshalBSONValue(bt bsontype.Type, data []byte) error {
if bt == bsontype.Null { if bt == bsontype.Null {
// we can't set nil in UnmarshalBSONValue (so we use default(struct)) // we can't set nil in UnmarshalBSONValue (so we use default(struct))
// Use mongoext.CreateGoExtBsonRegistry if you need to unmarsh pointer values
// https://stackoverflow.com/questions/75167597 // https://stackoverflow.com/questions/75167597
// https://jira.mongodb.org/browse/GODRIVER-2252 // https://jira.mongodb.org/browse/GODRIVER-2252
*t = RFC3339NanoTime{} *t = RFC3339NanoTime{}
@@ -115,6 +116,12 @@ func (t RFC3339NanoTime) DecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.Value
return err return err
} }
if val.Kind() == reflect.Ptr {
val.Set(reflect.ValueOf(&t))
} else {
val.Set(reflect.ValueOf(t))
}
return nil return nil
} }