Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get BinData UUID from Mongo as string

Tags:

mongodb

I currently have some ids stored in Mongo as UUIDs (necessary for processing). They get returned like this:

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

What would be an easy way to turn this value into a string for debugging?

Just to be clear - the application can handle the data fine. I just need a way to get the actual UUID from Mongo quickly.

like image 442
David Neale Avatar asked Nov 23 '11 14:11

David Neale


2 Answers

The answer to your question is more complicated that you would expect! The main reason it's complicated is that for historical reasons (unfortunately) different drivers have written UUIDs to the database using different byte orders. You don't mention which driver you are using, but I'll use the C# driver as an example.

Suppose I use the following code to insert a document:

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

If I then examine the document using the Mongo shell, it looks like this:

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

The Mongo shell has a built-in function called hex that you can use to display the binary value as a hex string:

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

Look carefully: the byte order of the hex string doesn't match the original UUID value used in the C# program. That's because the C# driver uses the byte order returned by Microsoft's ToByteArray method of the Guid class (which sadly returns the bytes in a bizarre order, which fact was not discovered for many months). Other drivers have their own idiosyncracies.

To help out with this we have some helper functions written in Javascript that can be loaded into the Mongo shell. They are defined in this file:

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

The Mongo shell can be told to process a file as it starts up by providing the name of the file on the command line (along with the --shell argument). Having loaded this file we have access to a number of helper functions to create and display BinData values that are UUIDs. For example:

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 } > 

In this example the toCSUUID function is used to display a BinData value as a CSUUID and the CSUUID function is used to create a BinData value for a UUID using the C# driver's byte ordering conventions so that we can query on a UUID. There are similar functions for the other drivers (toJUUID, toPYUUID, JUUID, PYUUID).

Some day in the future all drivers will standardize on a new binary subtype 4 with a standard byte order. In the meantime you have to use the appropriate helper function that matches whatever driver you are using.

like image 141
Robert Stam Avatar answered Oct 19 '22 13:10

Robert Stam


Use this function before your query:

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()); 

Result: "ea815826-0c02-e446-a984-00f62a687381"

like image 25
Todd Avatar answered Oct 19 '22 13:10

Todd