mongodbgobsonmgomongo-go

mgo is setting objectid to objectidhex, which doesnt seem to get read by Mongodb


I am trying to make a query using the ObjectId, and normally in mongodb you would do something like this

db.collection.findOne({"_id":objectid("5d9d90e5ed645489aae6df64")})

Which this works when I do a normal query but in go lang it gives it the value of

ObjectIdHex("5d9d90e5ed645489aae6df64")

instead which does not lead to a valid query.

i have read through the mgo documentation many times trying to use

bson.ObjectId("5d9d90e5ed645489aae6df64")

but it still makes it a hex which I don't understand. I have tried a few different combination of things with no like they were pretty much just shots in the dark.

Go Lang Handlers

package userhandlers

import (
    "log"
    "net/http"
    //"fmt"
    //"go.mongodb.org/mongo-driver/bson/primitive"
    //"go.mongodb.org/mongo-driver/bson"
    "labix.org/v2/mgo/bson"

    //Services
    databaseservice "malikiah.io/services/databaseService"
    passwordservice "malikiah.io/services/passwordService"

    //Structs
    userstructs "malikiah.io/structs/userStructs"
    databasestructs "malikiah.io/structs/databaseStructs"
)

func LoginHandler(response http.ResponseWriter, request *http.Request) {
    response.Header().Set("Content-Type", "application/json")
    response.WriteHeader(http.StatusOK)

    databaseQuery := databasestructs.Find{
        ID: bson.ObjectId(request.FormValue("_id")),
        MongoCollection: "users",
        Criteria: "_id",
        CriteriaValue: "",
        FindAll: false,
    }
    log.Println(databaseQuery)
    databaseservice.Login(databaseQuery)
}

Go Lang Structs

package databasestructs

import (
    //"go.mongodb.org/mongo-driver/bson/primitive"
    "labix.org/v2/mgo/bson"
)

type Find struct {
    ID                      bson.ObjectId   `json:"_id,omitempty" bson:"_id,omitempty"`
    MongoCollection         string              `json:"mongoCollection,omitempty" bson:"mongoCollection,omitempty"`
    Criteria                string              `json:"criteria,omitempty" bson:"criteria,omitempty"`
    CriteriaValue           string              `json:"criteriaValue,omitempty" bson:"criteriaValue,omitempty"`
    FindAll                 bool                `json:"findAll,omitempty" bson:"findAll,omitempty"`
}

Go Lang Functions

package databaseservice

import (
    "context"
    "log"

    //Structs
    userstructs "malikiah.io/structs/userStructs"
    databasestructs "malikiah.io/structs/databaseStructs"

    //"go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "gopkg.in/mgo.v2/bson"

)

func Find(databaseQuery databasestructs.Find) (result string) {
    // Set client options
    clientOptions := options.Client().ApplyURI("mongodb://localhost:27017")

    // Connect to MongoDB
    client, err := mongo.Connect(context.TODO(), clientOptions)

    // Database name
    db := client.Database("malikiah")
    collection := db.Collection(databaseQuery.MongoCollection)

    if err != nil {
        log.Fatal(err)
    }

    if databaseQuery.Criteria == "_id" {
        log.Println(databaseQuery.ID)
        result := collection.FindOne(context.TODO(), bson.M{databaseQuery.Criteria: databaseQuery.ID}).Decode(&result)
        log.Println(result)
    } else if databaseQuery.Criteria == "" {

    } else if databaseQuery.FindAll == true {

    } else {

    }
    return
}

Solution

  • Note that labix.org/v2/mgo is not maintained anymore, if you want to use mgo, use github.com/globalsign/mgo instead. Or the new, official mongo-go driver.

    bson.ObjectId is a type having string as its underlying type:

    type ObjectId string
    

    So when you fill your object like this:

    databaseQuery := databasestructs.Find{
        ID: bson.ObjectId(request.FormValue("_id")),
        MongoCollection: "users",
        Criteria: "_id",
        CriteriaValue: "",
        FindAll: false,
    }
    

    bson.ObjectId(request.FormValue("_id")) is "nothing more" than a type conversion. You convert the hex object ID string to bson.ObjectId, but this is not what you want. You want to parse the hex object ID. For that, use the bson.ObjectIdHex() function:

    databaseQuery := databasestructs.Find{
        ID: bson.ObjectIdHex(request.FormValue("_id")),
        MongoCollection: "users",
        Criteria: "_id",
        CriteriaValue: "",
        FindAll: false,
    }
    

    Note that bson.ObjectIdHex() will panic if the passed string is an invalid hex object ID. Use bson.IsObjectIdHex() to check it prior to calling bson.ObjectId(). For details, see Prevent runtime panic in bson.ObjectIdHex.

    If you would use the official driver instead of mgo, you could use primitive.ObjectIDFromHex() function to create the ObjectId, e.g.:

    id, err := primitive.ObjectIDFromHex(request.FormValue("_id"))
    if err != nil {
        // Handle error
        return
    }
    // If no error, you may use it:
    databaseQuery := databasestructs.Find{
        ID: id,
        // ...
    }