how to connect compose mongodb with golang - mongodb

I try to connect compose mongodb in bluemix with golang program but i get unsupported connection url option ssl. Here I give mongodb connection string got from composedb console. How to connect with remote host need syntax for connect?
session, err := mgo.Dial("mongodb://****:****#aws-us-east-1-portal.26.dblayer.com:20258/admin?ssl=true")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
c := session.DB("test").C("people")
err = c.Insert(&Person{"Ale", "+55 53 8116 9639"},
&Person{"Cla", "+55 53 8402 8510"})
if err != nil {
log.Fatal(err)
}
The error:
panic: unsupported connection URL option: ssl=true
goroutine 1 [running]:
panic(0x2130a0, 0xc82000a840)
/usr/local/go/src/runtime/panic.go:481 +0x3e6
main.main()
/Users/vit/gocode/src/mongmix/mmix.go:19 +0x9b
exit status 2

install "go get gopkg.in/mgo.v2"
package main
///////////////import mongo gopkg//////////////
import (
"fmt"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
//////////// add struct//////////////////////////
type Person struct {
Name string
Phone string
}
///// main function///////////
func main(){
fmt.Println("Hello world");
//////db connection ////////////
session, err := mgo.Dial("localhost:9494")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
///////////////db name/////////////
c := session.DB("sudheer").C("people")
err = c.Insert(&Person{"Ale", "+55 53 8116 9639"},
&Person{"Cla", "+55 53 8402 8510"})
if err != nil {
log.Fatal(err)
}
result := Person{}
err = c.Find(bson.M{"name": "Ale"}).One(&result)
if err != nil {
log.Fatal(err)
}
fmt.Println("Phone:", result.Phone)
}

IBM Bluemix Compose for Mongodb has a documentation available online here: https://console.bluemix.net/docs/services/ComposeForMongoDB/index.html#getting-started-with-compose-for-mongodb
Step 2 talks about connecting to your compose mongo db. There is a nodejs sample code provided in step 2. You will have to check connection string to mongodb in golang i.e. the syntax in golang.
I found out this article which explains connecting to IBM Compose mongodb from goland: https://www.compose.com/articles/connect-to-mongo-3-2-on-compose-from-golang/
hope this helps.

Related

Why I get an error "client disconnected" when trying to get documents from mongo collection in go?

I have mongo capped collection and a simple API, written on Go. I built and run it. When I try to sent Get request or simply go localhost:8000/logger in browser - my process closes. Debug shows this happens, while executing "find" in collection. It produces error "client is disconnected". Collection has 1 document, and debug shows it is connected with my helper.
Go version 1.13
My code:
func main() {
r := mux.NewRouter()
r.HandleFunc("/logger", getDocs).Methods("GET")
r.HandleFunc("/logger", createDoc).Methods("POST")
log.Fatal(http.ListenAndServe("localhost:8000", r))
}
func getDocs(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var docs []models.Logger
//Connection mongoDB with helper class
collection := helper.ConnectDB()
cur, err := collection.Find(context.TODO(), bson.M{})
if err != nil {
helper.GetError(err, w)
return
}
defer cur.Close(context.TODO())
for cur.Next(context.TODO()) {
var doc models.Logger
err := cur.Decode(&doc)
if err != nil {
log.Fatal(err)
}
docs = append(docs, doc)
}
if err := cur.Err(); err != nil {
log.Fatal(err)
}
json.NewEncoder(w).Encode(docs)
}
func ConnectDB() *mongo.Collection {
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://127.0.0.1:27017"))
if err != nil {
log.Fatal(err)
}
fmt.Println("Connected to MongoDB!")
logCollection := client.Database("local").Collection("loggerCollection")
return logCollection
}
According to the documentation, the call to mongo.NewClient doesn't ensure that you can connect the Mongo server. You should first call mongo.Client.Ping() to verify if you can connect to the database or not.
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://127.0.0.1:27017"))
if err != nil {
log.Fatal(err)
}
if err := client.Ping(context.TODO(), readpref.Primary()); err != nil {
// Can't connect to Mongo server
log.Fatal(err)
}
There could be several reasons behind failing to connect, the most obvious one is incorrect setup of ports. Is your mongodb server up and listening on port 27017? Is there any change you're running mongodb with Docker and it's not forwarding to the correct port?
I faced similar issue , read #Jay answer it definitely helped , as I checked my MongoDB was running using "MongoDB Compass" , then I changed the location of my insert statement , previously I was calling before the call of "context.WithTimeout". Below is working code.
package main
import (
"context"
"log"
"time"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Book struct {
Name string `json:"name,omitempty"`
PublisherID string `json:"publisherid,omitempty"`
Cost string `json:"cost,omitempty"`
StartTime string `json:"starttime,omitempty"`
EndTime string `json:"endtime,omitempty"`
}
func main() {
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017"))
if err != nil {
log.Fatal(err)
}
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
err = client.Connect(ctx)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
testCollection := client.Database("BooksCollection").Collection("BooksRead")
inserRes, err := testCollection.InsertOne(context.TODO(), Book{Name: "Harry Potter", PublisherID: "IBN123", Cost: "1232", StartTime: "2013-10-01T01:11:18.965Z", EndTime: "2013-10-01T01:11:18.965Z"})
log.Println("InsertResponse : ", inserRes)
log.Println("Error : ", err)
}
I can see document inserted in console as well as in "MongoDB Comapass."
In heiper function "ConnectDB" after "NewClient" I must use "client.Connect(context.TODO())"
before any other use of client

How to solve "command find requires authentication" using Golang and MongoDriver

I need help to fix the error. I'm using IBM mongo services.
go version go1.13.6 darwin/amd64
mongo driver version 1.2.1
The connection is working, I can read and write but sometimes it returns
: command find requires authentication and command insert requires authentication
MONGO_DB_URI=mongodb://username:password:port,host/dbname?authSource=admin&replicaSet=replset&connect=direct&alias=default
Connect:
func ConnectDatabase() *mongo.Client {
clientOptions := options.Client().ApplyURI(os.Getenv("MONGO_DB_URI"))
ctx, _ := context.WithTimeout(context.Background(), 30*time.Second)
var err error
client, err = mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
ctx, _ = context.WithTimeout(context.Background(), 10*time.Second)
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
return nil
}
fmt.Println("Connected to MongoDB!")
return client
}
Read:
func FindAll(collectionName string, query bson.M) (*mongo.Cursor, error) {
collection := client.Database("dbname").Collection(collectionName)
singleResult, err := collection.Find(context.TODO(), query)
return singleResult, err
}
Read:
ctx, _ := context.WithTimeout(context.Background(), 20*time.Second)
cur, err := mongo.GetCollection("collection_name").Find(ctx, createQuery())
if err != nil {
log.Println(err.Error())
}
I'm using the same database and the same configurations at our another Python Project. No exceptions.
There is a difference between connecting to a DB and performing operations on the DB.
Mongo lets you connect without authentication because you have to be able to connect to be able to authenticate.
var cred options.Credential
cred.AuthSource = YourAuthSource
cred.Username = YourUserName
cred.Password = YourPassword
// set client options
clientOptions := options.Client().ApplyURI(os.Getenv("MONGO_DB_URI")).SetAuth(cred)
//... the rest of your code
Hope this helps.

How to connect to MONGODB container with golang web app inside at another container

I have a golang web app that use mongodb. I create two containers: one for my_app and the other for mongodb.
I use the official mongo-go-driver/mongo.
var client *mongo.Client
//create a mongo.Client
client, err = mongo.NewClient("mongodb://localhost:27017")
//client, err = mongo.NewClient("mongodb://my_first_mongodb:27017")
//client, err = mongo.NewClient("mongodb://:27017")
if err != nil {
log.Printf("could not create a mongo client: %v", err)
panic(err)
}
//connect it to your running MongoDB server
ctx1, cancel1 := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel1()
//Connect initializes the Client by starting background monitoring goroutines.
err = client.Connect(ctx1)
if err != nil {
log.Printf("could not connect with mongodb: %v", err)
panic(err)
}
fmt.Println("trying to start mongodb for my app")
ctx2, cancel2 := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel2()
err = client.Ping(ctx2, nil)
if err != nil {
log.Printf("no ping to mongo db could not connect with mongodb: %v", err)
panic(err)
}
My problem is that I don't know how get(connect) the address ip (localhost) of mongodb inside a container. if I use
client, err = mongo.NewClient("mongodb://localhost:27017")
doesn't work. but if inside a docker-compose I set the container name (my_first_mongodb) and I use this code:
client, err = mongo.NewClient("mongodb://my_first_mongodb:27017")
is all fine and it is working.
The problem with this solution is that:
Because Docker container names must be unique, you cannot scale a service beyond 1 container if you have specified a custom name. Attempting to do so results in an error here.
Any help please.
Thanks

Golang and MongoDb remote access fail (server returned error on SASL authentication step: Authentication failed.)

I am trying to connect to remote MongoDB database (Mongolab) from Go with mgo library but getting error panic: server returned error on SASL authentication step: Authentication failed. Here is my code
package main
import (
"fmt"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
)
type Person struct {
Name string
Phone string
}
func main() {
session, err := mgo.Dial("mongodb://<dbusername>:<dbpassword>#ds055855.mlab.com:55855")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
c := session.DB("catalog").C("History")
err = c.Insert(&Person{"Ale", "+55 53 8116 9639"},
&Person{"Cla", "+55 53 8402 8510"})
if err != nil {
log.Fatal(err)
}
result := Person{}
err = c.Find(bson.M{"name": "Ale"}).One(&result)
if err != nil {
log.Fatal(err)
}
fmt.Println("Phone:", result.Phone)
}
How can I fix this? And of course instead of stars in my code i write my login and password.
Please check if you have added users for your Mongolab database instance (https://mongolab.com/databases/catalog#users in case if your DB name is catalog) because by default your users list is empty (account user/password != database user/password).
Also add /<databasename> to the end of your connection string - mongodb://*******:*******#ds045795.mongolab.com:45795/databasename.

Configuring mongo with gin golang framework

I'm trying to configure mongo in my Go app. I'm using the Gin framework. I'm also using the mgo V2 driver for mongo. I want to connect to mongo as a middlware. Here's what I got:
func Run(cfg common.Config) error {
doWorkResource := &DoWorkResource{db: dbmap}
r := gin.New()
r.Use(middleware.DB())
r.POST("/register", doWorkResource.Register)
r.POST("/login", doWorkResource.Login)
r.Run(cfg.SvcHost)
return nil
}
This is the DB function:
func DB() gin.HandlerFunc {
session, err := mgo.Dial("localhost:27017")
if err != nil {
panic(err)
}
defer session.Close()
return func(c *gin.Context) {
s := session.Clone()
db := s.DB("testing").C("testData")
err = db.Insert(&Person{"Ale", "+55 53 8116 9639"},
&Person{"Cla", "+55 53 8402 8510"})
if err != nil {
log.Fatal(err)
}
c.Next()
}
}
type Person struct {
Name string
Phone string
}
The insertion is executed if I run it directly from the main function, but not if it's run from the DB() function. In fact, I logged from within the return statement in the DB() function and nothing in there is being executed. I have a feeling I need to call it as an argument to one of my endpoints, but when I do that I get
cannot use middleware.DB (type func() gin.HandlerFunc) as type gin.HandlerFunc in argument to r.RouterGroup.POST
Looks like your problem is right here:
defer session.Close()
What you're really doing when you register the middleware is not call that middleware every time a call comes in, but defining what to do every time a call comes in. First you run a initial set of commands. That would be this part:
session, err := mgo.Dial("localhost:27017")
if err != nil {
panic(err)
}
defer session.Close()
And then you return a set of instructions to run every time one of your endpoints gets hit, that would be this part:
s := session.Clone()
db := s.DB("testing").C("testData")
err = db.Insert(&Person{"Ale", "+55 53 8116 9639"},
&Person{"Cla", "+55 53 8402 8510"})
if err != nil {
log.Fatal(err)
}
c.Next()
And when you return from the middleware initializer, it activates the defer statement. Then when the first call comes in and tries to run the instructions you returned in the form of a HandlerFunc it fails because the session it is trying to use has already been closed.