我正在使用MongoDB作为我正在构建的Rails应用程序的后端。默认情况下,Mongo会为其记录生成24个字符的十六进制ID,以便更轻松地进行分片,因此我的网址看起来像:
example.com/companies/4b3fc1400de0690bf2000001/employees/4b3ea6e30de0691552000001
哪个不太漂亮。我想坚持使用Rails url约定,但也要将这些ID保留在数据库中。我认为一个愉快的妥协是使用更多字符将这些hex id压缩为更短的集合,所以它们看起来像:
example.com/companies/3ewqkvr5nj/employees/9srbsjlb2r
然后在我的控制器中,我将反转压缩,获取原始的十六进制ID并使用它来查找记录。
我的问题是,来回转换这些ID的最佳方法是什么?我当然希望它们尽可能短,但也是安全且易于转换的。
谢谢!
答案 0 :(得分:5)
您可以在高于16
的基数中表示十六进制ID,以使其字符串表示更短。 Ruby内置支持使用从2
到36
的基础。
b36 = '4b3fc1400de0690bf2000001'.hex.to_s(36)
# => "29a6dblglcujcoeboqp"
要将其转换回24个字符的字符串,您可以执行以下操作:
'%024x' % b36.to_i(36)
# => "4b3fc1400de0690bf2000001"
要实现更好的“压缩”,您可以将基数中的ID表示为高于36
。有一些Ruby库可以帮助你。 all-your-base
gem就是这样一个库。
我推荐基本62
代表,因为它只使用0-9
,a-z
和A-Z
字符,这意味着默认情况下它是网址安全的。
答案 1 :(得分:1)
即使使用基础62表示,您最终仍会使用仍然难以处理的16个字符ID:
'4b3fc1400de0690bf2000001'.hex.to_base_62
# => "UHpdfMzq7jKLcvyr"
Sidestepping Rails约定,另一个折衷方案是使用“URL id”作为对象created_at
日期的基本32表示。
aCompany.created_at
# => Sat Aug 13 20:05:35 -0500 2011
aCompany.created_at.to_i.to_s(32)
# => "174e7qv"
通过这种方式,您可以获得超短ID(7个字符),而无需跟踪特殊用途属性(在MongoMapper中,只需在模型中添加timestamps!
即可获得自动created_at
和updated_at
属性)。
答案 2 :(得分:0)
您可以使用base64缩短版本。确保使用' - '和'_'代替'+'和'/'。你也可以砍掉padding =。
将十六进制值转换为base 64的代码
def MD5hex2base64(str)
h1=[].clear
# split the 32 byte hex into a 16 byte array
16.times{ h1.push(str.slice!(0,2).hex) }
# pack (C* = unsigned char), (m = base64 encoded output)
[h1.pack("C*")].pack("m")
end