【问题标题】:Get BinData UUID from Mongo as string从 Mongo 获取 BinData UUID 作为字符串
【发布时间】:2018-09-22 10:17:50
【问题描述】:

我目前有一些 id 作为 UUID 存储在 Mongo 中(处理所必需的)。他们得到这样的回报:

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

有什么简单的方法可以将此值转换为字符串以进行调试?

要明确一点 - 应用程序可以很好地处理数据。我只需要一种快速从 Mongo 获取实际 UUID 的方法。

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    您的问题的答案比您预期的要复杂!它复杂的主要原因是由于历史原因(不幸的是)不同的驱动程序使用不同的字节顺序将 UUID 写入数据库。您没有提及您使用的是哪个驱动程序,但我将使用 C# 驱动程序作为示例。

    假设我使用以下代码插入一个文档:

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

    如果我随后使用 Mongo shell 检查文档,它看起来像这样:

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

    Mongo shell 有一个名为 hex 的内置函数,您可以使用它来将二进制值显示为十六进制字符串:

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

    仔细看:十六进制字符串的字节顺序与 C# 程序中使用的原始 UUID 值不匹配。这是因为 C# 驱动程序使用 Microsoft 的 Guid 类的 ToByteArray 方法返回的字节顺序(遗憾的是,它以奇怪的顺序返回字节,这个事实已经好几个月没有被发现了)。其他司机也有自己的特点。

    为了解决这个问题,我们有一些用 Javascript 编写的帮助函数,可以加载到 Mongo shell 中。它们在此文件中定义:

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

    可以通过在命令行上提供文件名(以及 --shell 参数)来告诉 Mongo shell 在启动时处理文件。加载此文件后,我们可以访问许多帮助函数来创建和显示作为 UUID 的 BinData 值。例如:

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

    在此示例中,toCSUUID 函数用于将 BinData 值显示为 CSUUID,CSUUID 函数用于使用 C# 驱动程序的字节顺序约定为 UUID 创建 BinData 值,以便我们可以查询 UUID。其他驱动程序(toJUUID、toPYUUID、JUUID、PYUUID)也有类似的功能。

    在未来的某一天,所有驱动程序都将在具有标准字节顺序的新二进制子类型 4 上进行标准化。与此同时,您必须使用与您正在使用的任何驱动程序相匹配的适当帮助函数。

    【讨论】:

    • 这正是我想要的,谢谢!我不知道这背后的历史。
    • 我是不是梦到了这个,或者以前没有其他方法可以做到这一点?例如。 {"$uuid":"00112233-4455-6677-8899-aabbccddeeff"}
    • 甜心鬼,这太荒谬了。不过谢谢。
    • 如果你使用的是RoboMongo,这篇文章告诉你如何启用uuidhelpers.js:robomongo.org/articles/uuids.html
    • 谢谢,Mongo 团队似乎决定不对 BinData 对象编写任何文档...
    【解决方案2】:

    在查询之前使用此函数:

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

    结果: "ea815826-0c02-e446-a984-00f62a687381"

    【讨论】:

    • 如何以相反的方式进行转换,即从 GUID/UUID 字符串转换为二进制?
    • @user3495691 GUID/UUID字符串到二进制的转换是here
    【解决方案3】:

    如果你使用的是Java spring-data,你可以使用这个算法:

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

    【讨论】:

      【解决方案4】:
      def binaryToUUID(byte: Array[Byte]): String = {
      
        if (byte == null) null
      
        else {
          val bb = ByteBuffer.wrap(byte)
          new UUID(bb.getLong, bb.getLong()).toString
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2019-05-02
        • 1970-01-01
        • 2019-01-01
        • 2014-08-25
        • 1970-01-01
        • 1970-01-01
        • 2017-09-15
        • 2011-05-30
        相关资源
        最近更新 更多