0

My goal is to implement this code. Except instead of using sql I want to use mongoDB. I think there is an issue with how I handle my sessions.

I'm trying to use mgo to insert some user data into MongoDB via a Rest API. Whenever I open the mongo shell and run the show dbs command, the poll DB is not displayed. I'm using Postman to test the Rest API. Any ideas what am I might be doing wrong in the insertion process? I tried creating the collection first in the mongo shell and then running the CreateUser function but I still didnt see the poll DB get created.

User

type User struct {
    Id bson.ObjectId `json:"id" bson:"_id,omitempty"`
    Username string `json:"username"`
    Password string  `json:"password"`
    Email string `json:"email"`
}

UserDAO

type UserDAO struct {
    session *mgo.Session
}

Creating a session

func GetMongoSession() *mgo.Session {
    if mgoSession == nil {
        var err error
        mgoSession, err = mgo.Dial("localhost")
        mgoSession.SetMode(mgo.Monotonic, true)

        if err != nil {
            log.Fatal("Failed to start the Mongo session.")
        }
    }
    return mgoSession.Clone()
}

I pass a User struct into the CreateUser function that I create using Postman:

{
    "username":"uname",
    "password":"pass",
    "email":"[email protected]"
}

Then I just respond with the same struct and receive this output:

{
    "id": "",
    "username": "uname",
    "password": "pass",
    "email": "[email protected]"
}

Creating a user

func (dao *UserDAO) CreateUser(u *User) (*User, error) {
    //return errors.New("Not implemented")

    // Get "users" collection

    dao.session = GetMongoSession()

    c := dao.session.DB("poll").C("user")

    defer dao.session.Close()

    //u.Id = bson.NewObjectId()
    err :=  c.Insert(u)

    if err != nil { 
        return nil, err
    }

    return u, nil
}

Http handler function

func (h *Handler) CreateUserReq(w http.ResponseWriter, r *http.Request) {

    // create new user using information from the Request object
    var user User
    decoder := json.NewDecoder(r.Body)

    if err := decoder.Decode(&user); err != nil {
        panic(err)
    }

    defer r.Body.Close()

    // Create new User
    u, err := h.UserService.CreateUser(&user)
    if err != nil {
        panic(err)
    }
    json.NewEncoder(w).Encode(*u)
}

Output of show dbs

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
3
  • first of all your getting pointer to user struct so u need to pass the address to to u struct like this in &u in your function of insert Commented Feb 11, 2018 at 17:32
  • I'm passing in a pointer to a user, CreateUser(u *User), so isn't the u that gets passing into c.Insert(u) already the address of the object? Commented Feb 11, 2018 at 18:33
  • where is dao *UserDAO defined in your code Commented Feb 11, 2018 at 19:06

2 Answers 2

2

Since, I don't have full context of your application so can't diagnose what exactly issue is with your code. But I came up with close example, which is working as expected.

Please see code below.

package main

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

type User struct {
    Id       bson.ObjectId `json:"id" bson:"_id,omitempty"`
    Username string        `json:"username"`
    Password string        `json:"password"`
    Email    string        `json:"email"`
}

func GetMongoSession() *mgo.Session {

    mgoSession, err := mgo.Dial("localhost")
    mgoSession.SetMode(mgo.Monotonic, true)

    if err != nil {
        log.Fatal("Failed to start the Mongo session.")
    }

    return mgoSession.Clone()
}

func CreateUser(u *User) (*User, error) {

    session := GetMongoSession()

    c := session.DB("poll").C("user")
    defer session.Close()

    err := c.Insert(u)

    if err != nil {
        return nil, err
    }

    return u, nil
}

func main() {

    var user = User{
        Email:    "[email protected]",
        Password: "My-secret",
        Username: "YouGuess",
    }

    _, e := CreateUser(&user)
    if e != nil {
        panic(e)
    }

    log.Println("Done...")
}

once you execute it, you should see a document in MongoDB provided that you successfully establish connection with proper credentials.

I can see following document in my collection:

{
    "_id": ObjectId("5a80941de0a0f75123aeb435"),
    "username": "YouGuess",
    "password": "My-secret",
    "email": "[email protected]"
}
Sign up to request clarification or add additional context in comments.

2 Comments

Sorry about the vagueness, I was trying not to make the post too long which might make things more complicated. What I'm doing in my code is implementing the architecture found here: medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1. The difference in mine would be instead of using the sql driver, I would use mgo. In the postgres.go file, I would use session *mgo.Session instesad of DB *sql.DB.
This ended up working for me after removing the DB I had created through the mongo shell and rerunning my code.
0

Try below code and first of all I check is my user struct contains data coming from postman and then there is one error also when you are assigning the session *mgo.Session to non-pointer dao.session variable. So I have changed many a things and it is working fine creating both database with poll name and creating a user collection with new document also I have removed ObjectId from User struct. Check it out

package main

import (
    "encoding/json"
    "gopkg.in/mgo.v2"
    "log"
    // "gopkg.in/mgo.v2/bson"
)

var (
    mgoSession     *mgo.Session
)

type UserDAO struct{
    session   *mgo.Session
}

type User struct {
    Username string `json:"username"`
    Password string  `json:"password"`
    Email string `json:"email"`
}

func GetMongoSession() *mgo.Session {
    if mgoSession == nil {
        var err error
        mgoSession, err = mgo.Dial("localhost")
        mgoSession.SetMode(mgo.Monotonic, true)

        if err != nil {
            log.Fatal("Failed to start the Mongo session.")
        }
    }
    return mgoSession.Clone()
}

func (dao *UserDAO) CreateUser(u *User) (*User, error) {
    //return errors.New("Not implemented")

    // Get "users" collection

    session := GetMongoSession()
    // log.Println(session)

    c := session.DB("poll").C("user")

    defer session.Close()

    //u.Id = bson.NewObjectId()
    err :=  c.Insert(u)

    if err != nil { 
        return nil, err
    }

    return u, nil
}

func main(){
    // this data will come from postman in your case
    jsonStr := []byte(`{
            "username":"uname",
            "password":"pass",
            "email":"[email protected]"
        }
    `)

    var user User
    err  := json.Unmarshal(jsonStr, &user)
    if err != nil{
        log.Println(err)
    }

    var dao *UserDAO

    dao.CreateUser(&user)
}

My collection output is:-

{
    "_id" : ObjectId("5a80993f32fcc2489f995aaf"),
    "username" : "uname",
    "password" : "pass",
    "email" : "[email protected]"
}

you don't need to create a Object id for new document it will be created itself when inserting a new document. Also If you wants top just create a collection using golang and then insert data you can create it explicitly. Go through this function create collection

3 Comments

I figured an Object Id would be created on insertion but was not sure, thanks for clarifying. I created the "poll" db and the "user" collection. I then ran my Postman request to create the user and did a db.user.find() in the mongo shell. There was no output though so I dont think the insert worked.
I updated the code in the original question to include my UserDAO struct. dao.session is of type *User so that should be ok. The link I posted is essentially what my code is trying to do.
I have tried yor code but it panics every time I assign session to your dao struct session variable in this line dao.session = GetMongoSession(). you can try above code it is working fine. I have tested it completely

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.