-
Notifications
You must be signed in to change notification settings - Fork 0
/
services.go
138 lines (124 loc) · 4.33 KB
/
services.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package grf
import (
"context"
"fmt"
"log"
"strings"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)
// Generic function to add objects to the database.
// models.Object is stored in the objects collection.
// Automatically adds the record to the collection with a plural, lowercase name.
func Create[K interface{}](database *mongo.Database, object K) (*mongo.InsertOneResult, error) {
collection, ctx, cancel := getCollectionAndContext(database, object)
defer cancel()
res, err := collection.InsertOne(ctx, object)
if err != nil {
log.Println("Error adding object to database.", err)
return nil, err
}
log.Println("Inserted record to " + collection.Name() + " collection.")
return res, err
}
// Reads all the objects of the given type.
func Read[K any](database *mongo.Database, objects *[]K) error {
collection, ctx, cancel := getCollectionAndContext(database, objects)
defer cancel()
cur, err := collection.Find(ctx, bson.D{})
if err != nil {
log.Println("error retrieving all objects of "+collection.Name(), err)
return err
}
err = cur.All(ctx, objects)
if err != nil {
log.Println("error getting data from cursor "+collection.Name(), err)
return err
}
return nil
}
func ReadOne[K any](database *mongo.Database, object *K, id string) error {
collection, ctx, cancel := getCollectionAndContext(database, object)
defer cancel()
// Converting the id from the hex string to the ObjectID format that mongo use
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
log.Println("Error converting id to ObjectId:", err)
return err
}
filter := bson.D{{Key: "_id", Value: objectID}}
log.Println("Filter: ", filter)
err = collection.FindOne(ctx, filter).Decode(&object)
log.Println("Object: ", object)
if err != nil {
log.Println("Error finding the one", err)
return err
}
return nil
}
func ReplaceOne[K any](database *mongo.Database, object *K, id string) error {
collection, ctx, cancel := getCollectionAndContext(database, object)
defer cancel()
// Converting the id from the hex string to the ObjectID format that mongo use
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
log.Println("Error converting id to ObjectId:", err)
return err
}
filter := bson.D{{Key: "_id", Value: objectID}}
res, err := collection.ReplaceOne(ctx, filter, *object)
if err != nil {
log.Println("Error replacing object:", err)
return err
}
log.Println("Replaced object.", res.ModifiedCount)
return nil
}
// about as dumb as it gets. Works for atomics. Wouldn't recommend for anything with dependencies.
func Delete[K any](database *mongo.Database, id string) error {
collection, ctx, cancel := getCollectionAndContext(database, *new(K))
defer cancel()
// Converting the group id from the hex string to the ObjectID format that mongo use
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
log.Println("Error converting id to ObjectId:", err)
return err
}
filter := bson.D{{Key: "_id", Value: objectID}}
res, err := collection.DeleteOne(ctx, filter)
if err != nil {
log.Println("Error deleting object:", err)
return err
}
log.Println("Deleted object.", res.DeletedCount)
return nil
}
func getPlural(noun string) string {
// Model type name could be a variation of the following.
// package.model, *package.model, []package.model, *[]package.model
// We're extracting the model name and returning its plural.
// "*models.Todo" becomes "todos" || "*[]models.Box" becomes "boxes"
splits := strings.Split(strings.TrimPrefix(strings.TrimPrefix(noun, "*"), "[]"), ".")
noun = strings.ToLower(splits[len(splits)-1])
ends := []string{"s", "sh", "ch", "x", "z"}
for _, end := range ends {
if strings.HasSuffix(noun, end) {
return noun + "es"
}
}
return noun + "s"
}
func getCollection[K any](database *mongo.Database) *mongo.Collection {
object := new(K)
collectionName := getPlural(fmt.Sprintf("%T", object))
collection := database.Collection(collectionName)
return collection
}
func getCollectionAndContext[K any](database *mongo.Database, object K) (*mongo.Collection, context.Context, context.CancelFunc) {
collectionName := getPlural(fmt.Sprintf("%T", object))
collection := database.Collection(collectionName)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
return collection, ctx, cancel
}