/
insert.go
88 lines (77 loc) · 1.9 KB
/
insert.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package sutando
import (
"context"
"reflect"
"github.com/pkg/errors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
type insertOneResult *mongo.InsertOneResult
type insertManyResult *mongo.InsertManyResult
type insert struct {
col *mongo.Collection
data []bson.M
encoder bsonEncoder
}
func newInsert(collection *mongo.Collection, encoder bsonEncoder, p ...any) inserting {
ins := &insert{
col: collection,
data: make([]bson.M, 0, len(p)),
encoder: encoder,
}
name := reflect.TypeOf(p).Name()
for i := range p {
ins.handleData(p[i], name)
}
return ins
}
func (ins *insert) handleData(elem any, name string) {
rValue := reflect.ValueOf(elem)
rType := reflect.TypeOf(elem)
switch rValue.Kind() {
case reflect.Slice:
rName := rType.Name()
for i := 0; i < rValue.Len(); i++ {
ins.handleData(rValue.Index(i).Interface(), rName)
}
case reflect.Pointer:
ins.handleData(rValue.Elem().Interface(), name)
case reflect.Struct:
ins.data = append(ins.data, ins.encoder.Encode(elem, name))
case reflect.Map, reflect.Func:
return
default:
return
}
}
func (ins *insert) build() []any {
result := make([]any, 0, len(ins.data))
for i := range ins.data {
result = append(result, ins.data[i])
}
return result
}
func (ins *insert) Exec(ctx context.Context) (insertOneResult, insertManyResult, error) {
var (
err error
one insertOneResult
many insertManyResult
)
objects := ins.build()
switch len(objects) {
case 0:
return one, many, errors.New("mongo: object to insert should be pointer")
case 1:
one, err = ins.col.InsertOne(ctx, objects[0])
return one, many, ins.wrapDuplicateKeyErr(err)
default:
many, err = ins.col.InsertMany(ctx, objects)
return one, many, ins.wrapDuplicateKeyErr(err)
}
}
func (ins *insert) wrapDuplicateKeyErr(err error) error {
if mongo.IsDuplicateKeyError(err) {
return ErrDuplicatedKey
}
return err
}