Get BinData UUID from Mongo as string

后端 未结 4 918
悲&欢浪女
悲&欢浪女 2020-11-29 21:22

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

\"_id\" : new BinData(3, \"JliB6gIMRuSphAD2KmhzgQ         


        
相关标签:
4条回答
  • 2020-11-29 21:34
    def binaryToUUID(byte: Array[Byte]): String = {
    
      if (byte == null) null
    
      else {
        val bb = ByteBuffer.wrap(byte)
        new UUID(bb.getLong, bb.getLong()).toString
      }
    }
    
    0 讨论(0)
  • 2020-11-29 21:38

    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.

    0 讨论(0)
  • 2020-11-29 21:51

    If you are using Java spring-data, you can use this algorithm:

    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;
    }
    
    0 讨论(0)
  • 2020-11-29 21:56

    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"

    0 讨论(0)
提交回复
热议问题