从Go访问MongoDB

时间:2017-02-20 11:08:05

标签: mongodb go mgo

我使用Go访问MongoDB,如下所示:

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。但我需要在Time中将此日期作为转到clientConfigData

1 个答案:

答案 0 :(得分:2)

如果要在从/向MongoDB封送/解组值时更改值或进行类型转换,可以通过实现自定义封送/解组逻辑来实现。

您可以通过实施bson.Getterbson.Setter接口来实现此目的。在这些方法中,您可以使用编组/解组的值执行任何操作。

最简单的方法是使用附加字段扩展您的clientConfigData类型,该字段属于time.Time类型,您需要的值:

type clientConfigData struct {
    SMTPAssoc  int       `bson:"smtp_assoc"`
    PlanType   string    `bson:"plan_type"`
    EndDateStr string    `bson:"end_date"`
    EndDate    time.Time `bson:"-"`
}

标记值为bson:"-",因为我们不希望它出现在MongoDB中。

现在是自定义封送/取消逻辑:

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()负责"填充"你的struct值的原始值来自MongoDB,GetBSON()负责提供你想要保存的值(封送)。

加载时:SetBSON()首先按原样解组值,然后从EndDate日期值正确设置time.Time字段(类型为string)来自DB(EndDateStr)。

保存时:GetBSON()首先从EndDateStr字段填写EndDate字段(已保存的字段),然后返回,表示可以保存。< / p>

有一点需要注意:SetBSON()GetBSON()都会在其中创建一个新的my类型。这样做的原因是为了避免堆栈溢出。简单地返回clientConfigData类型的值很糟糕,因为我们实施了bson.Getterbson.Setter,因此SetBSON()GetBSON()会被无休止地调用。新的my类型没有这些方法,所以无限的#34;递归&#34;不会发生(type关键字会创建一个新类型,并且它不会继承&#34;底层类型的方法。)

另见相关/类似问题:Set default date when inserting document with time.Time field