I'm a beginner in both go and mongodb.
I try to decode a DocumentResult
into a struct using bson tags, and it does not work for a custom type wrapping a string.
Can it be done without changing the field's type to a string?
import (
"context"
"github.com/mongodb/mongo-go-driver/mongo"
)
type MyDoc struct {
SomeInt int `bson:"some_int"`
SomeString string `bson:"some_string,omitempty"`
CustomType MyType `bson:"custom_type,omitempty"`
}
type MyType string
const myType MyType = "ABCD"
func main() {
//Connect to db
client, _ := mongo.Connect(context.Background(), "mongodb://localhost:27017", nil)
db := client.Database("example_db")
collection := db.Collection("col")
//Insert document
docToInsert := MyDoc{42, "The Answer", myType}
collection.InsertOne(nil, docToInsert)
//Retrieve document
filterDoc := MyDoc{SomeInt: 42}
resultDoc := &MyDoc{}
result := collection.FindOne(nil, filterDoc)
result.Decode(resultDoc)
println(resultDoc.SomeInt, resultDoc.SomeString, resultDoc.CustomType)
PRINTED RESULT: "42 The Answer" //"ABCD" is missing
Thanks in advance
I try to decode a DocumentResult into a struct using bson tags, and it does not work for a custom type wrapping a string
With your current MyType
, the document that would be stored in MongoDB would be as below:
{
"_id": ObjectId("..."),
"some_int": NumberLong("42"),
"some_string": "The Answer",
"custom_type": "ABCD"
}
Even though the underlying type is a string
, this could be tricky to decode with the current version of mongo-go-driver (v0.0.12) due to the type wrapping.
However, if you would like to have a custom type as such, you could change the struct into an embedded field instead. For example:
type MyDoc struct {
SomeInt int `bson:"some_int"`
SomeString string `bson:"some_string,omitempty"`
CustomType MyType `bson:"custom_type,omitempty"`
}
type MyType struct {
Value string `bson:"value,omitempty"`
}
var myType = MyType{Value: "ABCD"}
docToInsert := MyDoc{42, "The Answer", "ABCD"}
insertResult, err := collection.InsertOne(nil, docToInsert)
resultDoc := collection.FindOne(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
elem := &MyDoc{}
err = resultDoc.Decode(elem)
if err != nil {
log.Fatal(err)
}
fmt.Println(elem.SomeInt, elem.SomeString, elem.CustomType.Value)
// 42 The Answer ABCD
The document would be stored in MongoDB as below:
{
"_id": ObjectId("..."),
"some_int": NumberLong("42"),
"some_string": "The Answer",
"custom_type": {
"value": "ABCD"
}
}
Otherwise just use string
type directly because the resulting document in the database would be the same as the type wrapping version:
type MyDoc struct {
SomeInt int `bson:"some_int"`
SomeString string `bson:"some_string,omitempty"`
CustomType string `bson:"custom_type,omitempty"`
}
You may also find MongoDB Data Modeling a useful reference.