Skip to content

Commit d8fda66

Browse files
committed
feat: Implement repository pattern for MongoDB collections: User, Project, Channel, and Event
1 parent 9911846 commit d8fda66

5 files changed

Lines changed: 423 additions & 0 deletions

File tree

internal/database/database.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313

1414
type Service interface {
1515
Health() map[string]string
16+
GetDB() *mongo.Database
17+
GetCollection(name string) *mongo.Collection
1618
}
1719

1820
type service struct {
@@ -53,3 +55,17 @@ func (s *service) Health() map[string]string {
5355
"message": "It's healthy",
5456
}
5557
}
58+
59+
// GetDB returns the MongoDB database instance
60+
func (s *service) GetDB() *mongo.Database {
61+
dbName := os.Getenv("MONGODB_DATABASE")
62+
if dbName == "" {
63+
dbName = "trakrlog" // default database name
64+
}
65+
return s.db.Database(dbName)
66+
}
67+
68+
// GetCollection returns a specific collection from the database
69+
func (s *service) GetCollection(name string) *mongo.Collection {
70+
return s.GetDB().Collection(name)
71+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package repository
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"trakrlog/internal/database"
8+
"trakrlog/internal/models"
9+
10+
"go.mongodb.org/mongo-driver/bson"
11+
"go.mongodb.org/mongo-driver/bson/primitive"
12+
"go.mongodb.org/mongo-driver/mongo"
13+
)
14+
15+
type channelRepository struct {
16+
collection *mongo.Collection
17+
}
18+
19+
// NewChannelRepository creates a new channel repository instance
20+
func NewChannelRepository(dbService database.Service) ChannelRepository {
21+
return &channelRepository{
22+
collection: dbService.GetCollection("channels"),
23+
}
24+
}
25+
26+
func (r *channelRepository) Create(ctx context.Context, channel *models.Channel) error {
27+
channel.CreatedAt = time.Now()
28+
channel.UpdatedAt = time.Now()
29+
30+
result, err := r.collection.InsertOne(ctx, channel)
31+
if err != nil {
32+
return err
33+
}
34+
35+
channel.ID = result.InsertedID.(primitive.ObjectID)
36+
return nil
37+
}
38+
39+
func (r *channelRepository) FindByID(ctx context.Context, id string) (*models.Channel, error) {
40+
objectID, err := primitive.ObjectIDFromHex(id)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
var channel models.Channel
46+
err = r.collection.FindOne(ctx, bson.M{"_id": objectID}).Decode(&channel)
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
return &channel, nil
52+
}
53+
54+
func (r *channelRepository) FindByProjectID(ctx context.Context, projectID string) ([]*models.Channel, error) {
55+
objectID, err := primitive.ObjectIDFromHex(projectID)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
cursor, err := r.collection.Find(ctx, bson.M{"project_id": objectID})
61+
if err != nil {
62+
return nil, err
63+
}
64+
defer cursor.Close(ctx)
65+
66+
var channels []*models.Channel
67+
if err = cursor.All(ctx, &channels); err != nil {
68+
return nil, err
69+
}
70+
71+
return channels, nil
72+
}
73+
74+
func (r *channelRepository) Update(ctx context.Context, channel *models.Channel) error {
75+
channel.UpdatedAt = time.Now()
76+
77+
update := bson.M{
78+
"$set": bson.M{
79+
"name": channel.Name,
80+
"updated_at": channel.UpdatedAt,
81+
},
82+
}
83+
84+
_, err := r.collection.UpdateOne(ctx, bson.M{"_id": channel.ID}, update)
85+
return err
86+
}
87+
88+
func (r *channelRepository) Delete(ctx context.Context, id string) error {
89+
objectID, err := primitive.ObjectIDFromHex(id)
90+
if err != nil {
91+
return err
92+
}
93+
94+
_, err = r.collection.DeleteOne(ctx, bson.M{"_id": objectID})
95+
return err
96+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package repository
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"trakrlog/internal/database"
8+
"trakrlog/internal/models"
9+
10+
"go.mongodb.org/mongo-driver/bson"
11+
"go.mongodb.org/mongo-driver/bson/primitive"
12+
"go.mongodb.org/mongo-driver/mongo"
13+
"go.mongodb.org/mongo-driver/mongo/options"
14+
)
15+
16+
type eventRepository struct {
17+
collection *mongo.Collection
18+
}
19+
20+
// NewEventRepository creates a new event repository instance
21+
func NewEventRepository(dbService database.Service) EventRepository {
22+
return &eventRepository{
23+
collection: dbService.GetCollection("events"),
24+
}
25+
}
26+
27+
func (r *eventRepository) Create(ctx context.Context, event *models.Event) error {
28+
event.CreatedAt = time.Now()
29+
30+
result, err := r.collection.InsertOne(ctx, event)
31+
if err != nil {
32+
return err
33+
}
34+
35+
event.ID = result.InsertedID.(primitive.ObjectID)
36+
return nil
37+
}
38+
39+
func (r *eventRepository) FindByID(ctx context.Context, id string) (*models.Event, error) {
40+
objectID, err := primitive.ObjectIDFromHex(id)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
var event models.Event
46+
err = r.collection.FindOne(ctx, bson.M{"_id": objectID}).Decode(&event)
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
return &event, nil
52+
}
53+
54+
func (r *eventRepository) FindByChannelID(ctx context.Context, channelID string, limit, offset int64) ([]*models.Event, error) {
55+
objectID, err := primitive.ObjectIDFromHex(channelID)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
opts := options.Find().
61+
SetLimit(limit).
62+
SetSkip(offset).
63+
SetSort(bson.D{{Key: "created_at", Value: -1}})
64+
65+
cursor, err := r.collection.Find(ctx, bson.M{"channel_id": objectID}, opts)
66+
if err != nil {
67+
return nil, err
68+
}
69+
defer cursor.Close(ctx)
70+
71+
var events []*models.Event
72+
if err = cursor.All(ctx, &events); err != nil {
73+
return nil, err
74+
}
75+
76+
return events, nil
77+
}
78+
79+
func (r *eventRepository) FindByProjectID(ctx context.Context, projectID string, limit, offset int64) ([]*models.Event, error) {
80+
objectID, err := primitive.ObjectIDFromHex(projectID)
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
opts := options.Find().
86+
SetLimit(limit).
87+
SetSkip(offset).
88+
SetSort(bson.D{{Key: "created_at", Value: -1}})
89+
90+
cursor, err := r.collection.Find(ctx, bson.M{"project_id": objectID}, opts)
91+
if err != nil {
92+
return nil, err
93+
}
94+
defer cursor.Close(ctx)
95+
96+
var events []*models.Event
97+
if err = cursor.All(ctx, &events); err != nil {
98+
return nil, err
99+
}
100+
101+
return events, nil
102+
}
103+
104+
func (r *eventRepository) Update(ctx context.Context, event *models.Event) error {
105+
update := bson.M{
106+
"$set": bson.M{
107+
"title": event.Title,
108+
"description": event.Description,
109+
"icon": event.Icon,
110+
"tags": event.Tags,
111+
},
112+
}
113+
114+
_, err := r.collection.UpdateOne(ctx, bson.M{"_id": event.ID}, update)
115+
return err
116+
}
117+
118+
func (r *eventRepository) Delete(ctx context.Context, id string) error {
119+
objectID, err := primitive.ObjectIDFromHex(id)
120+
if err != nil {
121+
return err
122+
}
123+
124+
_, err = r.collection.DeleteOne(ctx, bson.M{"_id": objectID})
125+
return err
126+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package repository
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"trakrlog/internal/database"
8+
"trakrlog/internal/models"
9+
10+
"go.mongodb.org/mongo-driver/bson"
11+
"go.mongodb.org/mongo-driver/bson/primitive"
12+
"go.mongodb.org/mongo-driver/mongo"
13+
)
14+
15+
type projectRepository struct {
16+
collection *mongo.Collection
17+
}
18+
19+
// NewProjectRepository creates a new project repository instance
20+
func NewProjectRepository(dbService database.Service) ProjectRepository {
21+
return &projectRepository{
22+
collection: dbService.GetCollection("projects"),
23+
}
24+
}
25+
26+
func (r *projectRepository) Create(ctx context.Context, project *models.Project) error {
27+
project.CreatedAt = time.Now()
28+
project.UpdatedAt = time.Now()
29+
30+
result, err := r.collection.InsertOne(ctx, project)
31+
if err != nil {
32+
return err
33+
}
34+
35+
project.ID = result.InsertedID.(primitive.ObjectID)
36+
return nil
37+
}
38+
39+
func (r *projectRepository) FindByID(ctx context.Context, id string) (*models.Project, error) {
40+
objectID, err := primitive.ObjectIDFromHex(id)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
var project models.Project
46+
err = r.collection.FindOne(ctx, bson.M{"_id": objectID}).Decode(&project)
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
return &project, nil
52+
}
53+
54+
func (r *projectRepository) FindByUserID(ctx context.Context, userID string) ([]*models.Project, error) {
55+
objectID, err := primitive.ObjectIDFromHex(userID)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
cursor, err := r.collection.Find(ctx, bson.M{"user_id": objectID})
61+
if err != nil {
62+
return nil, err
63+
}
64+
defer cursor.Close(ctx)
65+
66+
var projects []*models.Project
67+
if err = cursor.All(ctx, &projects); err != nil {
68+
return nil, err
69+
}
70+
71+
return projects, nil
72+
}
73+
74+
func (r *projectRepository) Update(ctx context.Context, project *models.Project) error {
75+
project.UpdatedAt = time.Now()
76+
77+
update := bson.M{
78+
"$set": bson.M{
79+
"name": project.Name,
80+
"logo_base64": project.LogoBase64,
81+
"updated_at": project.UpdatedAt,
82+
},
83+
}
84+
85+
_, err := r.collection.UpdateOne(ctx, bson.M{"_id": project.ID}, update)
86+
return err
87+
}
88+
89+
func (r *projectRepository) Delete(ctx context.Context, id string) error {
90+
objectID, err := primitive.ObjectIDFromHex(id)
91+
if err != nil {
92+
return err
93+
}
94+
95+
_, err = r.collection.DeleteOne(ctx, bson.M{"_id": objectID})
96+
return err
97+
}

0 commit comments

Comments
 (0)