66 votes

Obtenir l'UUID des BinData de Mongo en tant que chaîne de caractères.

J'ai actuellement des identifiants stockés dans Mongo sous forme d'UUID (nécessaires pour le traitement). Ils sont renvoyés comme ceci :

"_id" : new BinData(3, "JliB6gIMRuSphAD2KmhzgQ==")

Quel serait le moyen le plus simple de transformer cette valeur en une chaîne de caractères pour le débogage ?

Pour être clair, l'application peut traiter les données sans problème. J'ai juste besoin d'un moyen d'obtenir rapidement l'UUID réel de Mongo.

92voto

Robert Stam Points 6689

La réponse à votre question est plus compliquée que vous ne le pensez ! La principale raison de cette complexité est que, pour des raisons historiques (malheureusement), différents pilotes ont écrit les UUID dans la base de données en utilisant différents ordres d'octets. Vous ne mentionnez pas le pilote que vous utilisez, mais je vais utiliser le pilote C# comme exemple.

Supposons que j'utilise le code suivant pour insérer un document :

var guid = new Guid("00112233-4455-6677-8899-aabbccddeeff");
collection.Insert(new BsonDocument {
    { "_id", guid },
    { "x", 1 }
});

Si j'examine ensuite le document en utilisant le shell Mongo, cela ressemble à ceci :

> db.test.findOne()
{ "_id" : BinData(3,"MyIRAFVEd2aImaq7zN3u/w=="), "x" : 1 }
>

Le shell Mongo dispose d'une fonction intégrée appelée hex que vous pouvez utiliser pour afficher la valeur binaire sous forme de chaîne hexadécimale :

> var doc = db.test.findOne()
> doc._id.hex()
33221100554477668899aabbccddeeff
>

Regardez bien : l'ordre des octets de la chaîne hexagonale ne correspond pas à la valeur UUID originale utilisée dans le programme C#. C'est parce que le pilote C# utilise l'ordre des octets renvoyé par la méthode ToByteArray de la classe Guid de Microsoft (qui renvoie malheureusement les octets dans un ordre bizarre, ce qui n'a pas été découvert avant plusieurs mois). D'autres pilotes ont leurs propres particularités.

Pour y remédier, nous disposons de quelques fonctions d'aide écrites en Javascript qui peuvent être chargées dans le shell Mongo. Elles sont définies dans ce fichier :

https://github.com/mongodb/mongo-csharp-driver/blob/master/uuidhelpers.js

On peut demander au shell Mongo de traiter un fichier au démarrage en fournissant le nom du fichier sur la ligne de commande (avec l'argument --shell). Après avoir chargé ce fichier, nous avons accès à un certain nombre de fonctions d'aide pour créer et afficher les valeurs BinData qui sont des UUID. Par exemple :

C:\mongodb\mongodb-win32-x86_64-2.0.1\bin>mongo --shell uuidhelpers.js
MongoDB shell version: 2.0.1
connecting to: test
type "help" for help
> var doc = db.test.findOne()
> doc._id.toCSUUID()
CSUUID("00112233-4455-6677-8899-aabbccddeeff")
> db.test.find({_id : CSUUID("00112233-4455-6677-8899-aabbccddeeff")})
{ "_id" : BinData(3,"MyIRAFVEd2aImaq7zN3u/w=="), "x" : 1 }
>

Dans cet exemple, la fonction toCSUUID est utilisée pour afficher une valeur BinData sous la forme d'un CSUUID et la fonction CSUUID est utilisée pour créer une valeur BinData pour un UUID en utilisant les conventions d'ordonnancement des octets du pilote C# afin de pouvoir effectuer une requête sur un UUID. Il existe des fonctions similaires pour les autres pilotes (toJUUID, toPYUUID, JUUID, PYUUID).

Un jour, dans le futur, tous les pilotes seront standardisés sur un nouveau sous-type binaire 4 avec un ordre d'octet standard. En attendant, vous devez utiliser la fonction d'aide appropriée qui correspond au pilote que vous utilisez.

0 votes

C'est exactement ce que je cherchais, merci ! Je n'avais aucune idée de l'histoire derrière tout ça.

0 votes

J'ai rêvé de ça, ou il n'y avait pas un autre moyen de le faire ? Par exemple. {"$uuid":"00112233-4455-6677-8899-aabbccddeeff"}

10 votes

Doux Jésus, c'est absurde. Merci quand même.

15voto

Todd Points 861

Utilisez cette fonction avant votre requête :

function ToGUID(hex) {
    var a = hex.substr(6, 2) + hex.substr(4, 2) + hex.substr(2, 2) + hex.substr(0, 2);
    var b = hex.substr(10, 2) + hex.substr(8, 2);
    var c = hex.substr(14, 2) + hex.substr(12, 2);
    var d = hex.substr(16, 16);
    hex = a + b + c + d;
    var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);
    return '"' + uuid + '"';
}

var id = new BinData(3, "JliB6gIMRuSphAD2KmhzgQ==");
ToGUID(id.hex());

Résultat : "ea815826-0c02-e446-a984-00f62a687381"

0 votes

Comment faire la conversion dans l'autre sens, c'est-à-dire de la chaîne GUID/UUID au binaire ?

1 votes

@user3495691 La conversion de la chaîne GUID/UUID en binaire est la suivante aquí

7voto

Leonardo Points 1983

Si vous utilisez Java spring-data, vous pouvez utiliser cet algorithme :

function ToUUID(hex) {
    var msb = hex.substr(0, 16);
    var lsb = hex.substr(16, 16);
    msb = msb.substr(14, 2) + msb.substr(12, 2) + msb.substr(10, 2) + msb.substr(8, 2) + msb.substr(6, 2) + msb.substr(4, 2) + msb.substr(2, 2) + msb.substr(0, 2);
    lsb = lsb.substr(14, 2) + lsb.substr(12, 2) + lsb.substr(10, 2) + lsb.substr(8, 2) + lsb.substr(6, 2) + lsb.substr(4, 2) + lsb.substr(2, 2) + lsb.substr(0, 2);
    hex = msb + lsb;
    var uuid = hex.substr(0, 8) + '-' + hex.substr(8, 4) + '-' + hex.substr(12, 4) + '-' + hex.substr(16, 4) + '-' + hex.substr(20, 12);

    return uuid;
}

0voto

game_changer Points 77
def binaryToUUID(byte: Array[Byte]): String = {

  if (byte == null) null

  else {
    val bb = ByteBuffer.wrap(byte)
    new UUID(bb.getLong, bb.getLong()).toString
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X