I'm VERY new to Go. From what I've seen in the examples of mGo, in order to query a collection and then read from it, you have to predefine the data that will be coming back in a struct.
type Person struct {
ID bson.ObjectId `bson:"_id,omitempty"`
Name string
Phone string
Timestamp time.Time
}
In PHP, the document was assigned to an array. This was perfect as one record may have completely different set of keys (may not contain Name or Phone but contain Email) and I could access it directly without setting up a predefined class / struct / variable.
Is there a way to do the same in Go / mGo?
There are multiple ways you can handle this.
Using a map:
var m bson.M
err := collection.Find(nil).One(&m)
check(err)
for key, value := range m {
fmt.Println(key, value)
}
Note that there's nothing special about bson.M as far as mgo is concerned. It's just a map[string]interface{}
type, and you can define your own map types and use them with mgo, even if they have a different value type.
Using a document slice:
The bson.D is a slice that is internally known to mgo, and it exists both to offer a more efficient mechanism and to offer a way to preserve the ordering of keys, which is used by MongoDB in some circumstances (for example, when defining indexes).
For example:
var d bson.D
err := collection.Find(nil).One(&d)
check(err)
for i, elem := range d {
fmt.Println(elem.Name, elem.Value)
}
Using an ,inline map field
The ,inline
bson flag can also be used in a map field, so that you can have your cake and eat it too. In other words, it enables using a struct so that manipulating known fields is convenient, and at the same time allows dealing with unknown fields via the inline map.
For example:
type Person struct {
ID bson.ObjectId `bson:"_id,omitempty"`
Name string
Phone string
Extra bson.M `bson:",inline"`
}