4

我正在使用 MongoDB 作为我正在构建的 Rails 应用程序的后端。默认情况下,Mongo 为其记录生成 24 个字符的十六进制 id 以使分片更容易,所以我的 URL 最终看起来像:

example.com/companies/4b3fc1400de0690bf2000001/employees/4b3ea6e30de0691552000001

这不是很漂亮。我想坚持 Rails url 约定,但也将这些 id 保留在数据库中。我认为一个愉快的折衷方案是使用更多字符将这些十六进制 id 压缩为更短的集合,因此它们看起来像:

example.com/companies/3ewqkvr5nj/employees/9srbsjlb2r

然后在我的控制器中,我会反转压缩,获取原始的十六进制 id 并使用它来查找记录。

我的问题是,来回转换这些 id 的最佳方法是什么?我当然希望它们尽可能短,而且 url 安全且易于转换。

谢谢!

4

3 回答 3

6

您可以以高于 的基数表示十六进制 id,16以使其字符串表示更短。Ruby 内置了对从2. 到36.

b36 = '4b3fc1400de0690bf2000001'.hex.to_s(36)
# => "29a6dblglcujcoeboqp"

要将其转换回 24 个字符的字符串,您可以执行以下操作:

'%024x' % b36.to_i(36)
# => "4b3fc1400de0690bf2000001"

为了实现更好的“压缩”,您可以将基数中的 id 表示为高于36. 有 Ruby 库可以帮助你。all-your-basegem 就是这样一个库。

我推荐基本62表示,因为它只使用0-9,a-zA-Z字符,这意味着默认情况下它是 URL 安全的。

于 2010-01-03T03:12:05.197 回答
1

即使使用 base 62 表示,您最终还是会得到仍然笨拙的 16 字符 id:

'4b3fc1400de0690bf2000001'.hex.to_base_62  
# => "UHpdfMzq7jKLcvyr"

created_at稍微回避一下 Rails 约定,另一个折衷方案是使用对象日期的base 32 表示作为“URL id” 。

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_atupdated_at属性是一件简单的事情)。

于 2011-08-14T01:16:07.400 回答
0

您可以使用 base64 使其更短。确保您使用的是“-”和“_”而不是“+”和“/”。你也可以砍掉填充=。

将十六进制值转换为基数 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
于 2010-01-02T23:14:51.470 回答