How do I model object data types in Go? Like mflix movie tomato property

In the struct the top level primitives are pretty straight forward, but how do I model more complex properties? I looked up object type and I think it’s bson.D ? See the Tomatoes property in the mflix sample movie collection from atlas I’m a beginner in both Go and MongoDb. Thanks everyone.

1 Like

Hey @Chris_Kettenbach,

I’m not sure if you bumped into bson annotations for native Go data structures. They make it so that you can model and interact with your MongoDB documents directly without having to use primitives like bson.D, bson.M, etc.

Here is a quick tutorial I wrote on the subject:

In regards to the mflix dataset, you could probably get away with doing something like the following:

type Movie struct {
    Plot string `bson:"plot"`
    Cast []string `bson:"cast"`
    Tomatoes bson.D `bson:"tomatoes"`
}

Of course, I personally wouldn’t want to use bson.D within my struct, so I would more than likely break it up into several data structures. This would leave me with something like the following:

type Viewer struct {
    Rating int32 `bson:"rating"`
    NumReviews int32 `bson:"numReviews"`
    Meter int32 `bson:"meter"`
}

type Tomatoes struct {
    Viewer Viewer `bson:"viewer"`
    LastUpdated time.Date `bson:"lastUpdated"`
}

type Movie struct {
    Plot string `bson:"plot"`
    Cast []string `bson:"cast"`
    Tomatoes Tomatoes `bson:"tomatoes"`
}

You might have to play around with the data structures a little bit because I didn’t test what I provided, but for the most part it should work out fine.

Does that answer your question?

Best,

1 Like

It looks like this

    {
        "_id": "573a13faf29313caabdec42e",
        "genres": [
            "Drama"
        ],
        "runtime": 90,
        "title": "Desde allè",
        "tomatoes": {
            "viewer": {}
        }
    }

This is exactly what I tried but the tomatoes field ends up empty. Also it didn’t seem to like time.Date for the lastUpdated, compiler says that’s not a type.

Thanks for the help!

Hey @Chris_Kettenbach,

So the data structures I gave you were a little incorrectly formatted. Some of the data types should have been changed. My fault for not having tested them prior.

I ran the following code:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"os"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type Viewer struct {
	Rating     float64 `bson:"rating,omitempty" json:"rating,omitempty"`
	NumReviews int     `bson:"numReviews,omitempty" json:"numReviews,omitempty"`
	Meter      int     `bson:"meter,omitempty" json:"meter,omitempty"`
}

type Tomatoes struct {
	Dvd         time.Time `bson:"dvd,omitempty" json:"dvd,omitempty"`
	LastUpdated time.Time `bson:"lastUpdated,omitempty" json:"lastUpdated,omitempty"`
	Viewer      Viewer    `bson:"viewer,omitempty" json:"viewer,omitempty"`
}

type Movie struct {
	ID       primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
	Plot     string             `json:"plot,omitempty" bson:"plot,omitempty"`
	Genres   []string           `json:"genres,omitempty" bson:"genres,omitempty"`
	Runtime  int                `json:"runtime,omitempty" bson:"runtime,omitempty"`
	Title    string             `json:"title,omitempty" bson:"title,omitempty"`
	Tomatoes Tomatoes           `json:"tomatoes,omitempty" bson:"tomatoes,omitempty"`
}

func main() {
	client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(os.Getenv("ATLAS_URI")))
	if err != nil {
		panic(err)
	}
	defer client.Disconnect(context.Background())

	database := client.Database("sample_mflix")
	moviesCollection := database.Collection("movies")

	ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)

	var movies []Movie
	opts := options.Find().SetLimit(3)
	cursor, err := moviesCollection.Find(ctx, bson.M{}, opts)
	if err != nil {
		panic(err)
	}
	if err = cursor.All(ctx, &movies); err != nil {
		panic(err)
	}

	data, _ := json.Marshal(movies)
	fmt.Println(string(data))
}

It seems that the results were as expected. Take a look at the following output from the code that I ran:

[
    {
        "_id": "573a1390f29313caabcd4135",
        "genres": [
            "Short"
        ],
        "plot": "Three men hammer on an anvil and pass a bottle of beer around.",
        "runtime": 1,
        "title": "Blacksmith Scene",
        "tomatoes": {
            "dvd": "0001-01-01T00:00:00Z",
            "lastUpdated": "2015-06-28T18:34:09Z",
            "viewer": {
                "meter": 32,
                "numReviews": 184,
                "rating": 3
            }
        }
    },
    {
        "_id": "573a1390f29313caabcd42e8",
        "genres": [
            "Short",
            "Western"
        ],
        "plot": "A group of bandits stage a brazen train hold-up, only to find a determined posse hot on their heels.",
        "runtime": 11,
        "title": "The Great Train Robbery",
        "tomatoes": {
            "dvd": "0001-01-01T00:00:00Z",
            "lastUpdated": "2015-08-08T19:16:10Z",
            "viewer": {
                "meter": 75,
                "numReviews": 2559,
                "rating": 3.7
            }
        }
    },
    {
        "_id": "573a1390f29313caabcd4323",
        "genres": [
            "Short",
            "Drama",
            "Fantasy"
        ],
        "plot": "A young boy, opressed by his mother, goes on an outing in the country with a social welfare group where he dares to dream of a land where the cares of his ordinary life fade.",
        "runtime": 14,
        "title": "The Land Beyond the Sunset",
        "tomatoes": {
            "dvd": "0001-01-01T00:00:00Z",
            "lastUpdated": "2015-04-27T19:06:35Z",
            "viewer": {
                "meter": 67,
                "numReviews": 53,
                "rating": 3.7
            }
        }
    }
]

Is this what you were looking for?

Best,

1 Like