【问题标题】:mgo is setting objectid to objectidhex, which doesnt seem to get read by Mongodbmgo 将 objectid 设置为 objectidhex,Mongodb 似乎无法读取它
【发布时间】:2020-02-06 15:17:21
【问题描述】:

我正在尝试使用 ObjectId 进行查询,通常在 mongodb 中你会做这样的事情

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

这在我执行普通查询时有效,但在 go lang 中它赋予它的值

ObjectIdHex("5d9d90e5ed645489aae6df64")

而不是导致有效的查询。

我已经多次阅读mgo文档尝试使用

bson.ObjectId("5d9d90e5ed645489aae6df64")

但它仍然使它成为我不明白的十六进制。我尝试了几种不同的组合,但它们几乎都只是在黑暗中拍摄。

Go 语言处理程序

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 语言结构

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 语言函数

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
}

【问题讨论】:

    标签: mongodb go bson mgo mongo-go


    【解决方案1】:

    请注意,labix.org/v2/mgo 不再维护,如果您想使用mgo,请改用github.com/globalsign/mgo。或者新的官方mongo-go driver

    bson.ObjectId 是一个以string 作为其基础类型的类型:

    type ObjectId string
    

    所以当你像这样填充你的对象时:

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

    bson.ObjectId(request.FormValue("_id")) 是“仅此而已”,然后是 conversion 类型。您将十六进制对象 ID 字符串转换为 bson.ObjectId,但这不是您想要的。您想要解析十六进制对象 ID。为此,请使用bson.ObjectIdHex() 函数

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

    请注意,如果传递的字符串是无效的十六进制对象 ID,bson.ObjectIdHex() 将出现紧急情况。在调用bson.ObjectId() 之前使用bson.IsObjectIdHex() 进行检查。详情请见Prevent runtime panic in bson.ObjectIdHex

    如果你想使用官方驱动而不是mgo,你可以使用primitive.ObjectIDFromHex()函数来创建ObjectId,例如:

    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,
        // ...
    }
    

    【讨论】:

    • 所以我之前用的是原语,后来我换了,因为我看到每个人都在用这个。但这是我在单值上下文中使用原语.ObjectIDFromHex(request.FormValue("_id")) ```多值原语。ObjectIDFromHex() 时遇到的问题
    • @Malikiah 见Multiple values in single-value context。请参阅编辑后的答案。
    • 是的,认为它需要像这样 ``` objectID, _ := original.ObjectIDFromHex(request.FormValue("_id")) ```
    • 所以现在我从查询结果中得到了这个错误......“无法将无效解码为字符串类型”不确定现在发生了什么 D:
    • @Malikiah 我现在看不到您的实际代码,但您在问题中发布的代码混合了mgomongo-go(官方驱动程序)。确保你不要那样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多