一尘不染

为什么我无法使用golang的mgo库找到ID?

go

我在golang中使用mgo库进行mongo操作,这是我的代码:

session.SetMode(mgo.Monotonic, true)
coll := session.DB("aaaw_web").C("cron_emails")
var result Result
fmt.Printf("%v", message.ID)
err = coll.FindId(bson.ObjectId(message.ID)).One(&result)
fmt.Printf("%v", result)
fmt.Println(err)

我得到这个输出:

595f2c1a6edcba0619073263
{ObjectIdHex("") 0   0  0    0 {         0    false 0    } 0 0 0  0 0 0 0}
ObjectIDs must be exactly 12 bytes long (got 24)
not found

但是我检查了一下,文档存在于mongo中,但是到这里没有结果,我不知道我在想什么…


阅读 257

收藏
2020-07-02

共1个答案

一尘不染

如错误消息所提示,对象ID的长度恰好为12个字节(12个字节的数据)。您看到的24个字符长的ID是ID的12个字节的十六进制表示形式(1个字节=>
2个十六进制数字)。

使用该bson.ObjectIdHex()函数获取bson.ObjectId十六进制表示形式是否可用的值。

err = coll.FindId(bson.ObjectIdHex(message.ID)).One(&result)

对于相反的方向,您可以使用ObjectId.Hex()此答案中详细介绍的方法:从mgo查询获取ObjectIdHex值

与key关联的值"_id"的类型bson.ObjectId仅为a string

bson.M是一个类型map[string]interface{},因此您需要Type断言才能将id作为以下形式获取ObjectId:

objid, ok := m["_id"].(ObjectId)
if !ok {
    panic("Not ObjectId")
}

并且ObjectId具有一个ObjectId.Hex()可以完全返回您想要的方法的方法:对象ID作为“纯”十六进制字符串:

fmt.Println(objid.Hex())

备择方案objid可以简单地转换为,string因为其基础类型为string。因此,您可以使用许多其他选项将其转换为十六进制string:

hexid := fmt.Sprintf("%x", string(objid))

如果只想打印它,则可以直接执行以下操作:

fmt.Printf("%x", string(objid))

注意:将其转换为string非常重要,否则fmt程序包将调用其String()方法,该方法将产生类似的字符串,ObjectIdHex("537f700b537461b70c5f0000")而这将被转换为十六进制,这显然不是您想要的。

或者,您可以使用encoding/hex包和hex.EncodeToString()函数:

hexid := hex.EncodeToString([]byte(objid))

您在代码中所做的是一个简单的类型转换(给定message.ID为type
string),并且语法是有效的,因为的基础类型bson.ObjectIdstring,因此基本上将24个字符解释为bson.ObjectIdtype,但是它是无效ObjectId值,因为它将是24个字节而不是12个字节。

2020-07-02