Skip to content

Commit 45a3cf0

Browse files
committed
Moved esmongo.
1 parent 9e7b95e commit 45a3cf0

27 files changed

+1252
-300
lines changed

client.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package mongodata
2+
3+
import (
4+
"context"
5+
6+
"go.mongodb.org/mongo-driver/event"
7+
"go.mongodb.org/mongo-driver/mongo"
8+
"go.mongodb.org/mongo-driver/mongo/options"
9+
"go.mongodb.org/mongo-driver/mongo/readpref"
10+
)
11+
12+
func Connect(
13+
ctx context.Context,
14+
uri string,
15+
m *event.CommandMonitor,
16+
) (*mongo.Client, error) {
17+
o := options.Client().ApplyURI(uri)
18+
if m != nil {
19+
o = o.SetMonitor(m)
20+
}
21+
client, err := mongo.Connect(ctx, o)
22+
if err != nil {
23+
return nil, err
24+
}
25+
26+
if err := client.Ping(ctx, readpref.Primary()); err != nil {
27+
return nil, err
28+
}
29+
30+
return client, nil
31+
}

collection.go

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package mongodata
2+
3+
import (
4+
"context"
5+
"errors"
6+
"iter"
7+
8+
"go.mongodb.org/mongo-driver/bson"
9+
"go.mongodb.org/mongo-driver/mongo"
10+
"go.mongodb.org/mongo-driver/mongo/options"
11+
)
12+
13+
var ErrNotFound = errors.New("not found")
14+
var ErrVersionMismatch = errors.New("version mismatch")
15+
16+
type Collection[M any] struct {
17+
collection *mongo.Collection
18+
}
19+
20+
func NewCollection[M any](collection *mongo.Collection) *Collection[M] {
21+
return &Collection[M]{collection}
22+
}
23+
24+
func (c *Collection[M]) Insert(ctx context.Context, id string, m *M) error {
25+
_, err := c.collection.InsertOne(ctx,
26+
m)
27+
return err
28+
}
29+
30+
func (c *Collection[M]) Upsert(ctx context.Context, id string, m *M) error {
31+
_, err := c.collection.ReplaceOne(ctx,
32+
bson.M{"_id": id},
33+
m,
34+
options.Replace().SetUpsert(true))
35+
return err
36+
}
37+
38+
func (c *Collection[M]) Replace(ctx context.Context, filter FilterBuilder, m *M) error {
39+
result, err := c.collection.ReplaceOne(ctx,
40+
filter.Build(),
41+
m)
42+
if err != nil {
43+
return err
44+
}
45+
46+
if result.MatchedCount == 0 {
47+
return ErrVersionMismatch
48+
}
49+
50+
return nil
51+
}
52+
53+
func (c *Collection[M]) Get(ctx context.Context, id string) (*M, error) {
54+
m, err := decode[M](c.collection.FindOne(ctx,
55+
bson.M{"_id": id}))
56+
if errors.Is(err, mongo.ErrNoDocuments) {
57+
err = ErrNotFound
58+
}
59+
60+
return &m, err
61+
}
62+
63+
func (c *Collection[M]) Delete(ctx context.Context, id string) error {
64+
_, err := c.collection.DeleteOne(ctx, bson.M{"_id": id})
65+
return err
66+
}
67+
68+
func (c *Collection[M]) GetList(ctx context.Context, filter FilterBuilder, sort *SortBuilder) iter.Seq2[*M, error] {
69+
return func(yield func(*M, error) bool) {
70+
f := filter.Build()
71+
o := sort.Build()
72+
result, err := c.collection.Find(ctx, f, o)
73+
if err != nil {
74+
yield(nil, err)
75+
return
76+
}
77+
78+
defer result.Close(ctx)
79+
80+
for result.Next(ctx) {
81+
m, err := decode[M](result)
82+
if err != nil {
83+
if errors.Is(err, mongo.ErrNoDocuments) {
84+
err = ErrNotFound
85+
}
86+
yield(nil, err)
87+
return
88+
}
89+
90+
if !yield(&m, nil) {
91+
return
92+
}
93+
}
94+
}
95+
}
96+
97+
type Change[M any] struct {
98+
Value M
99+
Token string
100+
}
101+
102+
func newChange[M any](cs *mongo.ChangeStream) (Change[M], error) {
103+
m, err := decode[M](cs)
104+
return Change[M]{Value: m, Token: cs.ResumeToken().String()}, err
105+
}
106+
107+
func (c *Collection[M]) Watch(ctx context.Context, pipeline any, token string) iter.Seq2[Change[M], error] {
108+
return func(yield func(Change[M], error) bool) {
109+
o := options.ChangeStream()
110+
if token != "" {
111+
o.SetResumeAfter(bson.Raw(token))
112+
}
113+
114+
cs, err := c.collection.Watch(ctx, pipeline, o)
115+
if err != nil {
116+
yield(Change[M]{Token: token}, err)
117+
return
118+
}
119+
120+
defer cs.Close(ctx)
121+
122+
for cs.Next(ctx) {
123+
if c, err := newChange[M](cs); err != nil {
124+
yield(c, err)
125+
return
126+
} else if !yield(c, nil) {
127+
return
128+
}
129+
}
130+
}
131+
}

dataaccess.go

-43
This file was deleted.

decoder.go

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package mongodata
2+
3+
type decoder interface {
4+
Decode(any) error
5+
}
6+
7+
func decode[M any](decoder decoder) (M, error) {
8+
var m M
9+
return m, decoder.Decode(&m)
10+
}

entity.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package mongodata
2+
3+
type Entity[I EntityID] interface {
4+
ID() I
5+
Version() int
6+
}
7+
8+
type EntityID interface {
9+
String() string
10+
}
11+
12+
type Event interface {
13+
Type() string
14+
}

event_mapper.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package mongodata
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
)
7+
8+
type EventDefinition interface {
9+
ParseEvent(re modelEvent) (Event, error)
10+
}
11+
12+
type EventMapper map[string]EventDefinition
13+
14+
func (em EventMapper) ParseEvent(re modelEvent) (Event, error) {
15+
parser, ok := em[re.Type]
16+
if !ok {
17+
return nil, errors.New("no map")
18+
}
19+
20+
return parser.ParseEvent(re)
21+
}
22+
23+
type EventMap[T Event] struct{}
24+
25+
func (EventMap[T]) ParseEvent(re modelEvent) (Event, error) {
26+
var t T
27+
return t, json.Unmarshal(re.Data, t)
28+
}

event_mapper_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package mongodata
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"testing"
7+
)
8+
9+
type (
10+
entityID string
11+
)
12+
13+
func (e entityID) String() string { return string(e) }
14+
15+
type createEvent struct {
16+
ID string
17+
EntityID entityID
18+
Version int
19+
}
20+
21+
const (
22+
createEventType = "create_event"
23+
)
24+
25+
func (c createEvent) Type() string { return createEventType }
26+
27+
func TestEventMapper(t *testing.T) {
28+
em := EventMapper{
29+
createEventType: EventMap[createEvent]{},
30+
}
31+
d, _ := json.Marshal(createEvent{
32+
ID: "event1",
33+
EntityID: "entity1",
34+
Version: 1,
35+
})
36+
e := newModelEvent(createEventType, d)
37+
event, err := em.ParseEvent(*e)
38+
fmt.Print(err)
39+
fmt.Print(event)
40+
}

filter_builder.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package mongodata
2+
3+
import (
4+
"go.mongodb.org/mongo-driver/bson"
5+
)
6+
7+
type FilterBuilder map[string]any
8+
9+
func Filter() FilterBuilder {
10+
return FilterBuilder{}
11+
}
12+
13+
func (fb FilterBuilder) If(condition bool, a func(fb FilterBuilder)) FilterBuilder {
14+
if condition {
15+
a(fb)
16+
}
17+
return fb
18+
}
19+
20+
func (fb FilterBuilder) IfElse(condition bool, a func(fb FilterBuilder), b func(fb FilterBuilder)) FilterBuilder {
21+
if condition {
22+
a(fb)
23+
} else {
24+
b(fb)
25+
}
26+
return fb
27+
}
28+
29+
func (fb FilterBuilder) Property(key string, value any) FilterBuilder {
30+
fb[key] = value
31+
return fb
32+
}
33+
34+
func (fb FilterBuilder) PropertyIf(condition bool, key string, value any) FilterBuilder {
35+
if condition {
36+
fb[key] = value
37+
}
38+
return fb
39+
}
40+
41+
func (fb FilterBuilder) PropertyIfElse(condition bool, key string, a any, b any) FilterBuilder {
42+
if condition {
43+
fb[key] = a
44+
} else {
45+
fb[key] = b
46+
}
47+
return fb
48+
}
49+
50+
func (fb FilterBuilder) Build() bson.M {
51+
return bson.M(fb)
52+
}

go.mod

+10-21
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,18 @@
11
module github.com/cardboardrobots/mongodata
22

3-
go 1.19
3+
go 1.23.1
44

5-
require (
6-
github.com/cardboardrobots/repository v0.0.2
7-
github.com/go-playground/validator v9.31.0+incompatible
8-
go.mongodb.org/mongo-driver v1.10.3
9-
)
5+
require go.mongodb.org/mongo-driver v1.17.1
106

117
require (
12-
github.com/go-playground/locales v0.14.0 // indirect
13-
github.com/go-playground/universal-translator v0.18.0 // indirect
148
github.com/golang/snappy v0.0.4 // indirect
15-
github.com/google/go-cmp v0.5.9 // indirect
16-
github.com/klauspost/compress v1.15.11 // indirect
17-
github.com/leodido/go-urn v1.2.1 // indirect
18-
github.com/montanaflynn/stats v0.6.6 // indirect
19-
github.com/pkg/errors v0.9.1 // indirect
20-
github.com/stretchr/testify v1.8.0 // indirect
9+
github.com/klauspost/compress v1.17.10 // indirect
10+
github.com/montanaflynn/stats v0.7.1 // indirect
2111
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
22-
github.com/xdg-go/scram v1.1.1 // indirect
23-
github.com/xdg-go/stringprep v1.0.3 // indirect
24-
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
25-
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect
26-
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 // indirect
27-
golang.org/x/text v0.3.8 // indirect
28-
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
12+
github.com/xdg-go/scram v1.1.2 // indirect
13+
github.com/xdg-go/stringprep v1.0.4 // indirect
14+
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
15+
golang.org/x/crypto v0.27.0 // indirect
16+
golang.org/x/sync v0.8.0 // indirect
17+
golang.org/x/text v0.18.0 // indirect
2918
)

0 commit comments

Comments
 (0)