I'm currently working on a small application that allows users to rate certain objects, my database (MongoDB) structure looks like this
Movie {
Id int
Name string
}
Actor {
Id int
Name string
Age int
}
Movie_Actors {
Movie Movie
Actor Actor
}
User {
Id int
Username string
Password string
}
Rating {
Id int
User User
Actor Actor
Rating int
}
My problem begins when I want to select all Actors
in a Movie
where there are less than 5 Ratings
// db *mgo.Database
c := db.C('ratings')
err := c.Find(...)
For this problem, I would denormalize your schema a little to make querying in MongoDB more natural. Looking only at the types you need for this query, you might use the following:
type Movie struct {
Id bson.ObjectId `_id,omitempty`
Name string
Actors []bson.ObjectId
}
type Actor struct {
Id bson.ObjectId `_id,omitempty`
Name string
Age int
Ratings []Rating
NRatings int
}
Here the Movie directly embeds the Actor IDs, and the Actor keeps track of the number of ratings in a separate field from the ratings themselves. If you only wanted to run this single type of query, you could fully denormalize the data model by embedding the Movies directly into the Actors who played in them. This would simplify the query even more, but would also create a lot of duplication of information and prevent you from dealing with Movies as separate entities.
See the documentation on schema design for a discussion on these tradeoffs.
In this design, you can find the actors in the movie Fantastic Mr. Fox with fewer than 5 ratings using the following:
// Find the actors in the movie
var m Movie
db.C("movies").Find(bson.M{"name": "Fantastic Mr. Fox"}).One(&m)
// Filter the actors to find those with less than 5 ratings.
var results []Actor
db.C("actors").Find(bson.M{"_id": bson.M{"$in": m.Actors}, "nratings": bson.M{"$lt": 5}}).All(&results)
fmt.Println(results)