Reputation: 53
I am accessing MongoDB using Go as follows:
var configRes *clientConfigData
err := clientDB.
C(clientConfigCollection).
Find(bson.M{}).
One(&configRes)
if err != nil {
return nil, errors.Wrap(err, "finding config collection")
}
Where
type clientConfigData struct {
SMTPAssoc int `bson:"smtp_assoc"`
PlanType string `bson:"plan_type"`
EndDate string `bson:"end_date"`
}
Now since EndDate
in MongoDB is stored as string
so I declared EndDate
as string
. But I need to access this date as Go Time
in clientConfigData
.
Upvotes: 1
Views: 825
Reputation: 417472
If you want to change a value or do a type conversion when marshaling / unmarshaling your values from / to MongoDB, you may do it by implementing a custom marshaling / unmarshaling logic.
You can do this by implementing the bson.Getter
and bson.Setter
interfaces. Inside these methods, you may do whatever you want to with the values being marshaled / unmarshaled.
Easiest is to extend your clientConfigData
type with an additional field, one that will be of type time.Time
, the value you need:
type clientConfigData struct {
SMTPAssoc int `bson:"smtp_assoc"`
PlanType string `bson:"plan_type"`
EndDateStr string `bson:"end_date"`
EndDate time.Time `bson:"-"`
}
It has tag value bson:"-"
, because we don't want this to appear in MongoDB.
And now the custom marshaling / unmarhsaling logic:
const endDateLayout = "2006-01-02 15:04:05" // Use your layout here
func (c *clientConfigData) SetBSON(raw bson.Raw) (err error) {
type my clientConfigData
if err = raw.Unmarshal((*my)(c)); err != nil {
return
}
c.EndDate, err = time.Parse(endDateLayout, c.EndDateStr)
return
}
func (c *clientConfigData) GetBSON() (interface{}, error) {
c.EndDateStr = c.EndDate.Format(endDateLayout)
type my *clientConfigData
return my(c), nil
}
What happens here is that SetBSON()
is responsible to "populate" your struct value with the raw value coming from MongoDB, and GetBSON()
is responsible to provide a value you want to be saved (marshaled).
When loading: SetBSON()
first unmarshals the value as-is, then properly sets the EndDate
field (which is of type time.Time
) from the string
date value that came from the DB (EndDateStr
).
When saving: GetBSON()
first fills the EndDateStr
field (the one that is saved) from the EndDate
field, and then simply returns, signaling that it is ok to save.
One thing to note: both SetBSON()
and GetBSON()
create a new my
type inside them. The reason for this is to avoid stack overflow. Simply returning a value of type clientConfigData
is bad, because we implemented bson.Getter
and bson.Setter
, so SetBSON()
and GetBSON()
would get called endlessly. The new my
type does not have these methods, so endless "recursion" does not happen (the type
keyword creates a new type, and it does not "inherit" methods of the underlying type).
Also see related / similar question: Set default date when inserting document with time.Time field
Upvotes: 2