从Go访问MongoDB [英] Accessing MongoDB from Go
问题描述
我正在使用Go访问MongoDB,如下所示:
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")
}
哪里
type clientConfigData struct {
SMTPAssoc int `bson:"smtp_assoc"`
PlanType string `bson:"plan_type"`
EndDate string `bson:"end_date"`
}
现在,由于MongoDB中的EndDate
存储为string
,因此我将EndDate
声明为string
.但是我需要以clientConfigData
中的Go Time
的方式访问此日期.
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
.
推荐答案
如果在将值从/编组到MongoDB或将其编组到MongoDB时想要更改值或进行类型转换,则可以通过实现自定义的编组/解组逻辑.
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.
您可以通过实现 bson.Getter
来实现此目的 bson.Setter
接口.在这些方法中,您可以对已编组/未编组的值进行任何操作.
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.
最简单的方法是用一个附加字段扩展clientConfigData
类型,该字段的类型将为 time.Time
,您需要的值:
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:"-"`
}
它的标签值为bson:"-"
,因为我们不希望它出现在MongoDB中.
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
}
这里发生的事情是SetBSON()
负责用来自MongoDB的原始值填充"您的结构值,而GetBSON()
负责提供要保存(编组)的值.
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).
加载时:SetBSON()
首先按原样解组值,然后根据来自数据库(EndDateStr
)的string
日期值正确设置EndDate
字段(类型为time.Time
). ).
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
).
保存时:GetBSON()
首先从EndDate
字段填充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.
需要注意的一件事:SetBSON()
和GetBSON()
都在其中创建了新的my
类型.这样做的原因是为了避免堆栈溢出.仅返回类型为clientConfigData
的值是不好的,因为我们实现了bson.Getter
和bson.Setter
,因此SetBSON()
和GetBSON()
会被无限调用.新的my
类型没有这些方法,因此不会发生无休止的递归"(type
关键字创建一个新类型,并且不继承"基础类型的方法).
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
这篇关于从Go访问MongoDB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!