Accessing MongoDB from Go

后端 未结 1 730
栀梦
栀梦 2020-12-21 23:43

I am accessing MongoDB using Go as follows:

var configRes *clientConfigData
err := clientDB.
    C(clientConfigCollection).
    Find(bson.M{}).
    One(&         


        
相关标签:
1条回答
  • 2020-12-21 23:56

    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

    0 讨论(0)
提交回复
热议问题