如何使用 mgo(golang 客户端)查询 mongodb 中的 UUID 字段?
How to query UUID field in mongodb using mgo (golang client)?
我在 mongo collection 中查询 UUID 时遇到问题。 Mongo 文档结构如下:
{
"_id": {
"$oid": "5acf7faff5f02b0001e9fda1"
},
"j": {
"$uuid": "d0459793-3ec0-71fd-319e-b959af081db6"
},
"s": "ok",
"creation_date": {
"$date": "2018-04-12T15:47:59.003Z"
}
}
我想获取文档,传递 j
uuid(不是 ObjectID)。我创建了 mongo 连接,我得到了我的 collection,然后我尝试执行这个查询:
import (
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
...
var job *Job
uid, _ := uuid.FromString(m.ID)
e := c.Find(bson.M{"j": uid.String()}).One(&job)
但 e
始终等于 "not found"。
m.ID
是没有破折号的 uuid 字符串 -
所以我将它转换为 uuid.UUID
.
其他查询如 c.Find(bson.M{"s": "ok"}).All(&jobs)
工作正常,所以我确定连接 & collection。
使用 golang 1.11 & mongodb 3.6.
更新:
当我从 mongo 控制台执行 db.mycol.find()
时,结果是一个文档列表,如:
{ "_id" : ObjectId("5acf5b0ac7fb0700010040ac"), "j" : BinData(3,"amOjUW1oQQ6dNsvLrQuDhg=="), "s" : "ok", "creation_date" : ISODate("2018-04-12T13:11:38.365Z") }
所以我尝试像这样修改我的查询:
e := c.Find(bson.M{"j": bson.Binary{0x03, []byte(m.ID)}}).One(&job)
它仍然没有 return 文档。
您的 MongoDB 文档中的 j
属性 类型为 BinData
类型 3,因此在将其与字符串匹配时使用过滤器永远不会产生任何结果结果。
你的第二次尝试是在正确的轨道上。除了您要过滤 UUID 字符串的十六进制表示的 UTF-8 字节序列(这是 Go 在内存中存储字符串的方式,这是 string
-> []byte
转换的结果)。这将永远不会产生任何结果。
原因是您必须在 bson.Binary
中提供的二进制数据不是上述值,而是 UUID 的原始字节。
所以你要做的是对 UUID(以十六进制表示形式提供给你)进行十六进制解码,并使用此二进制数据。
data, err := hex.DecodeString(m.ID)
if err != nil {
panic(err)
}
e := c.Find(bson.M{"j": bson.Binary{
Kind: bson.BinaryUUIDOld,
Data: data,
}}).One(&job)
请注意,您必须将不带破折号的 UUID 传递给 hex.DecodeString()
,因此您甚至不需要任何第 3 方库来处理您拥有的 UUID 字符串。
另请注意,gopkg.in/mgo.v2
已不再维护。而是使用社区支持的分支:github.com/globalsign/mgo
.
这是因为UUID是以二进制数据存储的,需要将其转换为字符串才能查询
查看此答案,了解如何将 mongo 二进制数据转换为字符串并修改您的 FromString
Get BinData UUID from Mongo as string
如果您有要查询的 GUID,以下转换对我有用(重新排序关键字节,然后转换为十六进制解码):
func CsuuidToBinary(key string) []byte {
hexStr := strings.Replace(key, "-", "", -1)
first := hexStr[6:8] + hexStr[4:6] + hexStr[2:4] + hexStr[0:2]
second := hexStr[10:12] + hexStr[8:10]
third := hexStr[14:16] + hexStr[12:14]
fourth := hexStr[16:len(hexStr)]
hexStr = first + second + third + fourth
data, _ := hex.DecodeString(hexStr)
return data
}
然后:
data := CsuuidToBinary(guidKey)
var a A
err := collection.Find(bson.M{"SomeKey": bson.Binary{Kind: 0x03, Data: data,}}).One(&a)
我在 mongo collection 中查询 UUID 时遇到问题。 Mongo 文档结构如下:
{
"_id": {
"$oid": "5acf7faff5f02b0001e9fda1"
},
"j": {
"$uuid": "d0459793-3ec0-71fd-319e-b959af081db6"
},
"s": "ok",
"creation_date": {
"$date": "2018-04-12T15:47:59.003Z"
}
}
我想获取文档,传递 j
uuid(不是 ObjectID)。我创建了 mongo 连接,我得到了我的 collection,然后我尝试执行这个查询:
import (
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
...
var job *Job
uid, _ := uuid.FromString(m.ID)
e := c.Find(bson.M{"j": uid.String()}).One(&job)
但 e
始终等于 "not found"。
m.ID
是没有破折号的 uuid 字符串 -
所以我将它转换为 uuid.UUID
.
其他查询如 c.Find(bson.M{"s": "ok"}).All(&jobs)
工作正常,所以我确定连接 & collection。
使用 golang 1.11 & mongodb 3.6.
更新:
当我从 mongo 控制台执行 db.mycol.find()
时,结果是一个文档列表,如:
{ "_id" : ObjectId("5acf5b0ac7fb0700010040ac"), "j" : BinData(3,"amOjUW1oQQ6dNsvLrQuDhg=="), "s" : "ok", "creation_date" : ISODate("2018-04-12T13:11:38.365Z") }
所以我尝试像这样修改我的查询:
e := c.Find(bson.M{"j": bson.Binary{0x03, []byte(m.ID)}}).One(&job)
它仍然没有 return 文档。
您的 MongoDB 文档中的 j
属性 类型为 BinData
类型 3,因此在将其与字符串匹配时使用过滤器永远不会产生任何结果结果。
你的第二次尝试是在正确的轨道上。除了您要过滤 UUID 字符串的十六进制表示的 UTF-8 字节序列(这是 Go 在内存中存储字符串的方式,这是 string
-> []byte
转换的结果)。这将永远不会产生任何结果。
原因是您必须在 bson.Binary
中提供的二进制数据不是上述值,而是 UUID 的原始字节。
所以你要做的是对 UUID(以十六进制表示形式提供给你)进行十六进制解码,并使用此二进制数据。
data, err := hex.DecodeString(m.ID)
if err != nil {
panic(err)
}
e := c.Find(bson.M{"j": bson.Binary{
Kind: bson.BinaryUUIDOld,
Data: data,
}}).One(&job)
请注意,您必须将不带破折号的 UUID 传递给 hex.DecodeString()
,因此您甚至不需要任何第 3 方库来处理您拥有的 UUID 字符串。
另请注意,gopkg.in/mgo.v2
已不再维护。而是使用社区支持的分支:github.com/globalsign/mgo
.
这是因为UUID是以二进制数据存储的,需要将其转换为字符串才能查询
查看此答案,了解如何将 mongo 二进制数据转换为字符串并修改您的 FromString
Get BinData UUID from Mongo as string
如果您有要查询的 GUID,以下转换对我有用(重新排序关键字节,然后转换为十六进制解码):
func CsuuidToBinary(key string) []byte {
hexStr := strings.Replace(key, "-", "", -1)
first := hexStr[6:8] + hexStr[4:6] + hexStr[2:4] + hexStr[0:2]
second := hexStr[10:12] + hexStr[8:10]
third := hexStr[14:16] + hexStr[12:14]
fourth := hexStr[16:len(hexStr)]
hexStr = first + second + third + fourth
data, _ := hex.DecodeString(hexStr)
return data
}
然后:
data := CsuuidToBinary(guidKey)
var a A
err := collection.Find(bson.M{"SomeKey": bson.Binary{Kind: 0x03, Data: data,}}).One(&a)