最近在做使用mahout做协同过滤推荐的时候,发现无论是数据源还是推荐函数的接口user_id必须是Long型的变量
由于业务提供的user_id
是uuid
,所以是个字符串类型,并且item_id
(做的是岗位推荐,即为job_id)也是uuid
类型,于是另外再弄三张表uid-uuid
,jid-jjid
,uid-jid-score
的映射,但是这样做实在太麻烦了,我分析用户日志存储用户偏好表还要再多维护所有用户和所有岗位表,遂开始研究uuid
和uid
能不能做个映射。
首先了解一下UUID:
UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成的API。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字
UUID由以下几部分的组合:
- 当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
- 时钟序列。
- 全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
UUID的唯一缺陷在于生成的结果串会比较长。关于UUID这个标准使用最普遍的是微软的GUID(Globals Unique Identifiers)。其格式为:xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字
重点来了:
标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx (8-4-4-4-12) 其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字。
我现在需要处理的uuid
就是这个标准的UUID格式
,了解了UUID的构成以后我们就好办了:
1. 首先将uuid去掉连接符,从原先的uuid格式字符串转化为没有连接符的16进制字符串
2. 将16进制字符串转化为10进制数(内部使用mahout接口)
- 将10进制数再转回16进制的字符串(外部接口调用使用,记得补0)
用BigInt来存储这个唯一的十进制数,这样就构成了一种映射。
查了下python的内置uuid库的API用法:
UUID API
这里我直接用python
演示(python3
)
# Author:XzAmrzs
import uuid as uid2uuid
a = '0b27021f-3766-4b7b-b761-3c29768612fe'
# a = '4da5cc89-f65c-4658-8e78-2eb978e44b50'
x = uid2uuid.UUID(a)
print(x) # 0b27021f-3766-4b7b-b761-3c29768612fe
print(x.hex) # 0b27021f37664b7bb7613c29768612fe
uid = int(x.hex, 16) # 16进制字符串转10进制数
print(uid) # 14824050569154520558414196490098840318
uuid = "{:032x}".format(uid) # 注意这里要用0补齐32位,否则以0开头的16的转回来会丢0
print(uuid) # 0b27021f37664b7bb7613c29768612fe
print(uid2uuid.UUID(uuid)) # 0b27021f-3766-4b7b-b761-3c29768612fe
输出见下图
0b27021f-3766-4b7b-b761-3c29768612fe
0b27021f37664b7bb7613c29768612fe
14824050569154520558414196490098840318
0b27021f37664b7bb7613c29768612fe
0b27021f-3766-4b7b-b761-3c29768612fe
写完的时候google了一下发现墙外面也有不少讨论这个的,mahout官方也是说要做转换,直接用字符串类型进入推荐算法,效率会特别慢!
如下:
Why user id and item id must be long type ?
how to map uuid to userid in preference class to use mahout recommender
mahout-user mailing list archives:UUID based user IDs
参考:
Python 3.x 格式化输出字符串 % & format 笔记
python常用的十进制、16进制、字符串、字节串之间的转换
网友评论