Search code examples
jsonmongodbgostructmongo-go

How to create a Mongo document modelling it after two structs?


I made a simple api, using gingonic and a mongo database. I'm posting a simple object like this to the api to create a mongo document with the same shape. I found lots of examples using arrays but not with maps. I made this following the quickstart on www.mongodb.com.

{
    "email": "[email protected]",
    "profile": {
        "first_name": "Test",
        "last_name": "Example"
    }
}

And I have these two go structs (for user and profile)

type User struct {
    ID       primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
    Email    string             `json:"email" binding:"required,email" bson:"email"`
    Profile  *Profile           `json:"profile" binding:"required" bson:"profile,inline"`
}
type Profile struct {
    FirstName string `json:"first_name" binding:"required,min=3" bson:"first_name"`
    LastName  string `json:"last_name" binding:"required" bson:"last_name"`
}

And this is my create function:

func (dbc *Dbc) CreateUser(user *models.User) error {
    newUser := models.User{
        Email:    user.Email,
        Profile:  &models.Profile{
                    FirstName: user.Profile.FirstName, 
                    LastName: user.Profile.LastName},
    }
    _, err := dbc.GetUserCollection().InsertOne(dbc.ctx, newUser)
    return err
}

It will create a document, but like this (so without the subdocument profile):

{
    "email": "[email protected]",
    "first_name": "Test",
    "last_name": "Example"
}

Creating a new document without go structs works fine. So how do I model a json object using go structs containing subdocuments? I couldn't find much examples, not even on github. Anybody want to point me in the right direction?

newUser := bson.D{
    bson.E{Key: "email", Value: user.Email},
     bson.E{Key: "profile", Value: bson.D{
    bson.E{Key: "first_name", Value: user.Profile.FirstName},
    bson.E{Key: "last_name", Value: user.Profile.LastName},
     }},
}

Solution

  • You used bson:"profile,inline" tag, telling it to inline, that's why there is no subdocument in your DB. It does exactly what you ask it to do.

    Drop the ,inline option if you don't want to inline the profile but have a subdocument:

    Profile *Profile `json:"profile" binding:"required" bson:"profile"`