Search code examples
javascriptmongodbgobsondatabase

pass the mongodb bson.Objectid from JavaScript(fronend) to Go(backend)


I want to update MongoDB object attribute value by checking object id. that is type is bson.Objectid. I am using mgo.v2 MongoDB Golang driver. But in that case I send the PUT request to the update API. I send the object id HEX value as string to the Golang API. But there is error happening in my Golang side when decoding HEX value into bson.Object type variable.
How do I do this properly.


Frontend :

HEXVALUE = "57f54ef4d6e0ac55f6c7ff24"

var widget = {id: HEXVALUE, position: 2, type: 2, class: "normal"};

     $.ajax({
            url: 'api/widget',
            type: 'PUT',
            contentType: "application/json",
            data: JSON.stringify(widget),
            success: function (data) {
                console.log(data);
            },
            error: function (e) {
                console.log(e);
            }
     });

Go side (Server side):

type Widget struct {
    Id       bson.ObjectId `json:"id" bson:"_id"`
    Position int           `json:"position" bson:"position"`
    Type     int           `json:"type" bson:"type"`
    Class    string        `json:"class" bson:"class"`
}


func UpdateWidget(w http.ResponseWriter, r *http.Request) (error) {
    decoder := json.NewDecoder(r.Body)
    var widget models.DashboardWidget
    err := decoder.Decode(&widget)
    if err != nil {
        log.Error("There is error happening decoding widget: %v", err);
        return err;
    }
 reurn nil
};

Output

log error : There is error happening decoding widget

How to decode hex value into bson.ObjectId type.


Solution

  • 1-Decode hex value into bson.ObjectId type using:

    bson.ObjectIdHex("57f54ef4d6e0ac55f6c7ff24")
    

    2- To update MongoDB object attribute value by checking object id, you may use

    c.Update(bson.M{"_id": widget.Id}, widget)
    

    Here is the working code:

    package main
    
    import (
        "encoding/json"
        "fmt"
        "log"
        "net/http"
        "strings"
    
        "gopkg.in/mgo.v2"
        "gopkg.in/mgo.v2/bson"
    )
    
    func main() {
        session, err := mgo.Dial("localhost")
        if err != nil {
            panic(err)
        }
        defer session.Close()
        session.SetMode(mgo.Monotonic, true) // Optional. Switch the session to a monotonic behavior.
        c := session.DB("test").C("Widget")
        c.DropCollection()
        err = c.Insert(
            &Widget{bson.NewObjectId(), 1, 2, "c1"},
            &Widget{bson.NewObjectId(), 20, 2, "normal"},
            &Widget{bson.ObjectIdHex("57f54ef4d6e0ac55f6c7ff24"), 2, 2, "normal"})
        if err != nil {
            log.Fatal(err)
        }
    
        result := []Widget{}
        err = c.Find(bson.M{}).All(&result)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(result)
    
        s := `{"id":"57f54ef4d6e0ac55f6c7ff24","position":2,"type":2,"class":"normal"}`
        decoder := json.NewDecoder(strings.NewReader(s))
        var widget Widget
        err = decoder.Decode(&widget)
        if err != nil {
            panic(err)
        }
        fmt.Println(widget)
    
        c.Update(bson.M{"_id": widget.Id}, widget)
    
        result2 := []Widget{}
        err = c.Find(bson.M{}).All(&result2)
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(result2)
    
        //http.HandleFunc("/", UpdateWidget)
        //http.ListenAndServe(":80", nil)
    
    }
    func UpdateWidget(w http.ResponseWriter, r *http.Request) {
        decoder := json.NewDecoder(r.Body)
        var widget Widget //models.DashboardWidget
        err := decoder.Decode(&widget)
        if err != nil {
            log.Fatal(err)
        }
    }
    
    type Widget struct {
        Id       bson.ObjectId `json:"id" bson:"_id"`
        Position int           `json:"position" bson:"position"`
        Type     int           `json:"type" bson:"type"`
        Class    string        `json:"class" bson:"class"`
    }
    

    output:

    [{ObjectIdHex("57f62973c3176903402adb5e") 1 2 c1} {ObjectIdHex("57f62973c3176903402adb5f") 20 2 normal} {ObjectIdHex("57f54ef4d6e0ac55f6c7ff24") 2 2 normal}]
    {ObjectIdHex("57f54ef4d6e0ac55f6c7ff24") 2 2 normal}
    [{ObjectIdHex("57f62973c3176903402adb5e") 1 2 c1} {ObjectIdHex("57f62973c3176903402adb5f") 20 2 normal} {ObjectIdHex("57f54ef4d6e0ac55f6c7ff24") 2 2 normal}]
    

    3- Your Code has some typos:

    log error : There is error happening decoding widget

    This error belongs to

    err := decoder.Decode(&widget)
    

    Change it to this:

    err := decoder.Decode(&widget)
    if err != nil {
        log.Fatal(err)
    }
    

    to see exact error.


    Change

    var widget models.DashboardWidget
    

    to

    var widget Widget
    

    Like this:

    func UpdateWidget(w http.ResponseWriter, r *http.Request) {
        decoder := json.NewDecoder(r.Body)
        var widget Widget //models.DashboardWidget
        err := decoder.Decode(&widget)
        if err != nil {
            log.Fatal(err)
        }
    }
    

    and

    JSON.stringify(widget)
    

    generates:

    `{"id":"57f54ef4d6e0ac55f6c7ff24","position":2,"type":2,"class":"normal"}`
    

    This works fine:

    package main
    
    import (
        "encoding/json"
        "fmt"
        "strings"
    
        "gopkg.in/mgo.v2/bson"
    )
    
    func main() {
        s := `{"id":"57f54ef4d6e0ac55f6c7ff24","position":2,"type":2,"class":"normal"}`
        decoder := json.NewDecoder(strings.NewReader(s))
        var widget Widget
        err := decoder.Decode(&widget)
        if err != nil {
            panic(err)
        }
        fmt.Println(widget)
    }
    
    type Widget struct {
        Id       bson.ObjectId `json:"id" bson:"_id"`
        Position int           `json:"position" bson:"position"`
        Type     int           `json:"type" bson:"type"`
        Class    string        `json:"class" bson:"class"`
    }
    

    output:

    {ObjectIdHex("57f54ef4d6e0ac55f6c7ff24") 2 2 normal}