/
mongo.go
160 lines (129 loc) · 3.97 KB
/
mongo.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package LinkerMongo
import (
"context"
"github.com/go-park-mail-ru/2022_1_Wave/init/logger"
"github.com/go-park-mail-ru/2022_1_Wave/internal/domain"
"github.com/go-park-mail-ru/2022_1_Wave/internal/tools/utils"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"gopkg.in/mgo.v2/bson"
)
type LinkerRepo struct {
Coll *mongo.Collection
}
const (
urlField = "url"
hashField = "hash"
counterField = "counter"
length = 10
)
func NewLinkerMongoRepo(coll *mongo.Collection) (domain.LinkerRepo, error) {
idxUrl := mongo.IndexModel{
Keys: bson.M{urlField: 1},
Options: options.Index().SetUnique(true),
}
idxHash := mongo.IndexModel{
Keys: bson.M{hashField: 1},
Options: options.Index().SetUnique(true),
}
idxCounter := mongo.IndexModel{
Keys: bson.M{counterField: 1},
Options: options.Index().SetUnique(false),
}
idxes := []mongo.IndexModel{idxUrl, idxHash, idxCounter}
_, err := coll.Indexes().CreateMany(
context.TODO(),
idxes)
if err != nil {
return nil, err
}
return &LinkerRepo{
Coll: coll,
}, nil
}
type LinkInfo struct {
Url string
Hash string
Counter int64
}
func getHash() string {
hash := utils.RandStringRunes(length)
return hash
}
func (collection LinkerRepo) GetByField(field string, value string) (*LinkInfo, error) {
fromMongo := LinkInfo{}
filter := bson.M{field: value}
if err := collection.Coll.FindOne(context.TODO(), filter).Decode(&fromMongo); err != nil {
return nil, err
}
logger.GlobalLogger.Logrus.Warnln("success to get ", field, ": value: ", value)
return &fromMongo, nil
}
func (collection LinkerRepo) GetByHash(hash string) (*LinkInfo, error) {
return collection.GetByField(hashField, hash)
}
func (collection LinkerRepo) GetByUrl(url string) (*LinkInfo, error) {
return collection.GetByField(urlField, url)
}
func (collection LinkerRepo) Create(url string) (string, error) {
fromMongo, err := collection.GetByUrl(url)
if err == nil {
logger.GlobalLogger.Logrus.Warnln("success to get hash:", fromMongo.Hash, "for url:", fromMongo.Url)
return fromMongo.Hash, err
}
hash := getHash()
logger.GlobalLogger.Logrus.Warn("check hash:", hash)
for collection.Coll.FindOne(context.TODO(), bson.M{hashField: hash}) == nil {
logger.GlobalLogger.Logrus.Warn("check hash:", hash)
hash = getHash()
}
data := LinkInfo{
Url: url,
Hash: hash,
Counter: int64(0),
}
insertResult, err := collection.Coll.InsertOne(context.TODO(), data)
if err != nil {
logger.GlobalLogger.Logrus.Warn("error to insert:", err, " data:", data)
return "", err
}
logger.GlobalLogger.Logrus.Info("success insert single document:", insertResult, " id:", insertResult.InsertedID)
return data.Hash, nil
}
func (collection LinkerRepo) Get(hash string) (string, error) {
logger.GlobalLogger.Logrus.Info("in get url by hash...")
filter := bson.M{hashField: hash}
update := bson.M{
"$inc": bson.M{counterField: 1},
}
// Create an instance of an options and set the desired options
upsert := true
after := options.After
opt := options.FindOneAndUpdateOptions{
ReturnDocument: &after,
Upsert: &upsert,
}
// Find one result and update it
result := collection.Coll.FindOneAndUpdate(context.TODO(), filter, update, &opt)
err := result.Err()
if err != nil {
logger.GlobalLogger.Logrus.Warnln("error to get:", err, " hash:", hash)
return "", err
}
// Decode the result
fromCollection := LinkInfo{}
decodeErr := result.Decode(&fromCollection)
url := fromCollection.Url
counter := fromCollection.Counter
logger.GlobalLogger.Logrus.Info("success get url by hash:", hash, " url:", url, " counter:", counter)
return url, decodeErr
}
func (collection LinkerRepo) Count(hash string) (int64, error) {
logger.GlobalLogger.Logrus.Info("in count url by hash...")
fromMongo, err := collection.GetByHash(hash)
if err != nil {
return 0, err
}
logger.GlobalLogger.Logrus.Info("success get counter by hash:", hash, " counter:", fromMongo.Counter)
return fromMongo.Counter, nil
}