从Go访问MongoDB [英] Accessing MongoDB from Go

查看:89
本文介绍了从Go访问MongoDB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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.Getterbson.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆