【问题标题】:Accessing MongoDB from Go从 Go 访问 MongoDB
【发布时间】:2018-08-05 10:39:18
【问题描述】:

我正在使用 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。但我需要以 Go Time in clientConfigData 访问此日期。

【问题讨论】:

    标签: mongodb go mgo


    【解决方案1】:

    如果您想在从/到 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() 负责使用来自 MongoDB 的原始值“填充”您的结构值,而GetBSON() 负责提供您想要保存(封送)的值。

    加载时:SetBSON() 首先按原样解组值,然后从来自 DB (EndDateStr )。

    保存时:GetBSON()首先从EndDate字段填充EndDateStr字段(被保存的那个),然后简单地返回,表示可以保存。

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

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

    【讨论】:

    • 所以如果我们没有实现bson.Getterbson.Setter,我们可以简单地返回clienConfigData 对吗?但在这种情况下,我们最好不要。这是正确的吗?
    • 您的问题实际上没有意义,因为添加 GetBSON()SetBSON() 实现 GetterSetterGetterSetter是定义GetBSON()SetBSON() 的接口)。如果你不添加这些方法,就没有东西可以返回。
    • 非常感谢@icza
    • @icza 我只有一个问题,如何对从SetBSON返回的错误进行错误处理。
    • @SyedQasimRizvi 你不处理它,因为你不是打电话给SetBSON()的人。 mgo 包在从 MongoDB 加载值时检查该值是否实现 Setter,如果是,则调用其 SetBSON() 进行解组。是mgo 包需要处理它返回的error,它可能被您调用的外部函数(例如Find().All()Find().One())包装、记录或返回。
    猜你喜欢
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 2021-05-05
    相关资源
    最近更新 更多