Как запросить поле UUID в mongodb, используя mgo (клиент golang)? - PullRequest
0 голосов
/ 05 сентября 2018

У меня проблемы с запросами 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). Я создаю монго-соединение и получаю свою коллекцию, затем пытаюсь выполнить этот запрос:

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), работают нормально, поэтому я уверен в связи и сборе.

Использование golang 1.11 и mongodb 3.6.

UPDATE:

Когда я делаю 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)

И все равно документ не возвращается.

Ответы [ 3 ]

0 голосов
/ 05 сентября 2018

Это потому, что UUID хранится в виде двоичных данных, и вам необходимо преобразовать его в строку, чтобы запросить его

Посмотрите на этот ответ о том, как конвертировать монго биндата в строку и изменить ваш FromString

Получить Uin UID BinData из Mongo в виде строки

0 голосов
/ 27 ноября 2018

Если у вас есть 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)
0 голосов
/ 05 сентября 2018

Свойство j в ваших документах MongoDB имеет тип BinData тип 3, поэтому использование фильтра, в котором вы сопоставляете его со строкой, никогда не даст никаких результатов.

Ваша вторая попытка на правильном пути. За исключением того, что вы фильтруете байтовые последовательности UTF-8 шестнадцатеричного представления строки UUID (это то, как 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() без черточек, поэтому вам даже не нужны сторонние библиотеки для обработки имеющихся у вас строк UUID.

Также обратите внимание, что gopkg.in/mgo.v2 больше не поддерживается. Вместо этого используйте поддержку сообщества: github.com/globalsign/mgo.

...