2 Parts to the question.
1 is the mongodb query itself, the next is how to do it in mgo.
How do I query for 1 document of type category (the result should be of type category) where the slug: "general"
?
The reason I picked this layout is because I read the advantage of mongodb is performance with embedded "structs" however I fear I have to make "categories" and "forum" its own collection and rewrite a lot of code, I would like to avoid that because every view on the client side needs access to those models anyway and it would lead to 1-2 additional queries on each new page load (for category and forum) and the advantage of using mongodb would be gone.
And the followup question is, how would I update or delete one particular embedded document?
Is there a way to get the category document directly from mongodb without needing to either separate the documents or write find, update , delete functions in Go, and how?
this structure:
{
"_id" : ObjectId("5303d1a2d6194c0f27000001"),
"name" : "darko",
"description" : "darko",
"subdomain" : "darko",
"domain" : "mango.dev",
"created" : ISODate("2014-02-18T21:33:22.115Z"),
"category" : "Brains",
"owner" : "52b1d74dd6194c0646000002",
"members" : [
"52b1d74dd6194c0646000002"
],
"categories" : [
{
"_id" : ObjectId("5303d1a2d6194c0f27000003"),
"name" : "Admin and Moderator Area",
"slug" : "admin-and-moderator-area",
"adminonly" : true,
"membersonly" : false,
"forums" : [
{
"_id" : ObjectId("5303d1a2d6194c0f27000005"),
"name" : "Admin Discussion",
"slug" : "admin-discussion",
"text" : "This is the main forum for administrative topics."
}
]
},
{
"_id" : ObjectId("5303d1a2d6194c0f27000002"),
"name" : "General",
"slug" : "general",
"adminonly" : false,
"membersonly" : false,
"forums" : [
{
"_id" : ObjectId("5303d1a2d6194c0f27000004"),
"name" : "General Discussion",
"slug" : "general-discussion",
"text" : "Talk about everything and anything here in this general discussion forum"
}
]
}
]
}
or in go:
Community struct {
Id bson.ObjectId `bson:"_id,omitempty" json:"id"`
Name string `json:"name"`
Description string `bson:",omitempty" json:"description"`
Subdomain string `bson:",omitempty" json:"subdomain"`
Domain string `json:"domain"`
Created time.Time `json:"created"`
Category string `json:"category"`
Owner interface{} `json:"owner"` //userid
Members []interface{} `json:"members"` //userid
Moderators []interface{} `bson:",omitempty" json:"moderators"` //userid
Logo string `bson:",omitempty" json:"logo"` // relative path to file
Stylesheets []string `bson:",omitempty" json:"stylesheets"` // absolute path to files
Javascripts []string `bson:",omitempty" json:"javascripts"` // absolute path to files
Categories []*Category `json:"categories"`
}
Category struct {
Id bson.ObjectId `bson:"_id,omitempty" json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
AdminOnly bool `json:"-"`
MembersOnly bool `json:"-"`
Forums []*Forum `json:"forums"`
}
Forum struct {
Id bson.ObjectId `bson:"_id,omitempty" json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Text string `json:"text"`
Moderators []interface{} `bson:",omitempty" json:"moderators"` //userid
}
1.
Currently, there is no built in way for MongoDB to return subdocument, you can only return a projection of a document. That being said, you can still find the data you are looking for by using a projection.
The MongoDB manual gives you a very similar example. The query you should make is:
db.coll.find({}, {categories:{ $elemMatch: {"slug":"general"}}})
2.
With mgo
, the projection part is handled using Select. The mgo documentation states:
func (q *Query) Select(selector interface{}) *Query
Select enables selecting which fields should be retrieved for the results found.
Without having tried it, it should look something like this:
err := collection.Find(nil).Select(bson.M{"categories": bson.M{"$elemMatch": bson.M{"slug": "general"}}}).One(&result)
In order to get the nestled Category object, you can let result
be a containing struct:
type CategoryContainer struct {
Categories []Category{} // Or even [1]Category{} in this case
}
and then fetch the category simply:
category := result.Categories[0]
3.
For updating subdocuments, there are already good posts about that, such as: