github.com/christoph-karpowicz/db_mediator@v0.0.0-20210207102849-61a28a1071d8/internal/server/db/mongo.go (about) 1 package db 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 8 "github.com/christoph-karpowicz/db_mediator/internal/server/cfg" 9 "go.mongodb.org/mongo-driver/bson" 10 "go.mongodb.org/mongo-driver/mongo" 11 "go.mongodb.org/mongo-driver/mongo/options" 12 "go.mongodb.org/mongo-driver/mongo/readpref" 13 ) 14 15 // MongoDatabase implements Database interface for MongoDB database. 16 type mongoDatabase struct { 17 cfg *cfg.DbConfig 18 connectionString string 19 ctx context.Context 20 close context.CancelFunc 21 } 22 23 // CloseConnection closes the db connection. 24 func (d *mongoDatabase) CloseConnection() { 25 d.close() 26 } 27 28 // GetClient returns a connection client object. 29 func (d *mongoDatabase) GetClient() *mongo.Client { 30 authCredentials := options.Credential{Username: d.cfg.User, Password: d.cfg.Password} 31 clientOptions := options.Client().ApplyURI(d.connectionString).SetAuth(authCredentials) 32 client, err := mongo.NewClient(clientOptions) 33 if err != nil { 34 log.Fatal(err) 35 } 36 err = client.Connect(d.ctx) 37 if err != nil { 38 log.Fatal(err) 39 } 40 return client 41 } 42 43 // GetConfig returns information about the database, which was parsed from JSON. 44 func (d *mongoDatabase) GetConfig() *cfg.DbConfig { 45 return d.cfg 46 } 47 48 // Init creates the db connection string and context object. 49 func (d *mongoDatabase) Init() { 50 d.connectionString = fmt.Sprintf(`mongodb://%s:%d/%s`, 51 d.cfg.Host, 52 d.cfg.Port, 53 d.cfg.Name, 54 ) 55 ctx, cancel := context.WithCancel(context.Background()) 56 57 d.ctx = ctx 58 d.close = cancel 59 60 d.TestConnection() 61 } 62 63 // Insert inserts one row into a given collection. 64 func (d *mongoDatabase) Insert(inDto InsertDto) error { 65 fmt.Println(inDto) 66 client := d.GetClient() 67 collection := client.Database(d.cfg.Name).Collection(inDto.TableName) 68 69 insertResult, err := collection.InsertOne(context.TODO(), inDto.Values) 70 if err != nil { 71 dbErr := &DatabaseError{DBName: d.cfg.Name, ErrMsg: err.Error(), KeyName: inDto.KeyName, KeyValue: inDto.KeyValue} 72 return dbErr 73 } 74 if insertResult.InsertedID == nil { 75 dbErr := &DatabaseError{DBName: d.cfg.Name, ErrMsg: "could not insert document", KeyName: inDto.KeyName, KeyValue: inDto.KeyValue} 76 return dbErr 77 } 78 79 return nil 80 } 81 82 // Select selects data from the database, with or without filters. 83 func (d *mongoDatabase) Select(tableName string, conditions string) []map[string]interface{} { 84 var allDocuments []map[string]interface{} 85 86 client := d.GetClient() 87 collection := client.Database(d.cfg.Name).Collection(tableName) 88 89 var bsonConditions interface{} 90 if conditions != "" { 91 err := bson.UnmarshalExtJSON([]byte(conditions), true, &bsonConditions) 92 if err != nil { 93 panic(&DatabaseError{DBName: d.cfg.Name, ErrMsg: err.Error()}) 94 } 95 } else { 96 bsonConditions = bson.M{} 97 } 98 99 cur, err := collection.Find(d.ctx, bsonConditions) 100 if err != nil { 101 log.Fatal(&DatabaseError{DBName: d.cfg.Name, ErrMsg: err.Error()}) 102 } 103 104 for cur.Next(context.TODO()) { 105 var documentMap map[string]interface{} = make(map[string]interface{}) 106 err := cur.Decode(documentMap) 107 if err != nil { 108 log.Fatal(&DatabaseError{DBName: d.cfg.Name, ErrMsg: err.Error()}) 109 } 110 allDocuments = append(allDocuments, documentMap) 111 } 112 113 defer cur.Close(context.TODO()) 114 115 return allDocuments 116 } 117 118 // TestConnection pings the database. 119 func (d *mongoDatabase) TestConnection() { 120 c := d.GetClient() 121 err := c.Ping(context.Background(), readpref.Primary()) 122 if err != nil { 123 log.Fatal("Couldn't connect to the database", err) 124 } else { 125 log.Println("Connected!") 126 } 127 } 128 129 // Update updates a document with the provided key. 130 func (d *mongoDatabase) Update(upDto UpdateDto) error { 131 fmt.Println(upDto) 132 client := d.GetClient() 133 collection := client.Database(d.cfg.Name).Collection(upDto.TableName) 134 filter := bson.D{{upDto.KeyName, upDto.KeyValue}} 135 update := bson.D{ 136 {"$set", bson.D{ 137 {upDto.UpdatedColumnName, upDto.NewValue}, 138 }}, 139 } 140 141 updateResult, err := collection.UpdateOne(context.TODO(), filter, update) 142 if err != nil { 143 dbErr := &DatabaseError{DBName: d.cfg.Name, ErrMsg: err.Error(), KeyName: upDto.KeyName, KeyValue: upDto.KeyValue} 144 return dbErr 145 } 146 if updateResult.MatchedCount == 0 { 147 dbErr := &DatabaseError{DBName: d.cfg.Name, ErrMsg: "document with given key not found", KeyName: upDto.KeyName, KeyValue: upDto.KeyValue} 148 return dbErr 149 } 150 if updateResult.ModifiedCount == 0 { 151 dbErr := &DatabaseError{DBName: d.cfg.Name, ErrMsg: "no documents modified", KeyName: upDto.KeyName, KeyValue: upDto.KeyValue} 152 return dbErr 153 } 154 155 return nil 156 }