Best practice to maintain a mgo session

JonathanChaput picture JonathanChaput · Oct 26, 2014 · Viewed 20.2k times · Source

I'm currently using a mongodb with mgo lib for a web application, but I'm not sure if the way I'm using it, is good one ..

package db

import (
    "gopkg.in/mgo.v2"
)

const (
    MongoServerAddr = "192.168.0.104"
    RedisServerAddr = "192.168.0.104"
)

var (
    MongoSession, err = mgo.Dial(MongoServerAddr)

    MDB  = MongoSession.DB("message")
    MCol = MDB.C("new")
    MSav = MDB.C("save")

    UDB  = MongoSession.DB("account")
    UCol = UDB.C("user")
)

I init the db session and create variables who takes the collection and document value, so when I need to query a collection, I use the variable to make it.

Like that :

func UserExist(username string) bool {
    user := Users{}
    err := db.UCol.Find(bson.M{"username": username}).One(&user)
    if err != nil {
        return false
    } else {
        return true
    }
}

So is there a best practice or this one is fine ..? Thanks

Answer

Gustavo Niemeyer picture Gustavo Niemeyer · Oct 26, 2014

I suggest not using a global session like that. Instead, you can create a type that is responsible for all the database interaction. For example:

type DataStore struct {
    session *mgo.Session
}

func (ds *DataStore) ucol() *mgo.Collection { ... }

func (ds *DataStore) UserExist(user string) bool { ... }

There are many benefits to that design. An important one is that it allows you to have multiple sessions in flight at the same time, so if you have an http handler, for example, you can create a local session that is backed by an independent session just for that one request:

func (s *WebSite) dataStore() *DataStore {
    return &DataStore{s.session.Copy()}
}    

func (s *WebSite) HandleRequest(...) {
    ds := s.dataStore()
    defer ds.Close()
    ...
}

The mgo driver behaves nicely in that case, as sessions are internally cached and reused/maintained. Each session will also be backed by an independent socket while in use, and may have independent settings configured, and will also have independent error handling. These are issues you'll eventually have to deal with if you're using a single global session.