位运算在多维搜索中的应用

最近在做特征平台的改造,需要接入新的特征类别。一个特征可能同时属于多个类别,且平台要支持多种类别同时查询,原有的设计结构无法直接扩展,存储和查询需要做兼容改造。通过位运算的特性进行了设计优化,特此记录。

问题描述

现有的特征平台支持两类特征:在线特征、离线特征。

创建新的特征时,可以设置特征类别:

  • 情形一:勾选在线特征
  • 情形二:勾选离线特征
  • 情形三:同时勾选在线特征、离线特征

即一个特征可能属于在线特征,或者属于离线特征,或者同时属于在线和离线特征。

由于数据库中特征类别的字段为整形数字,而非数组,存储现状是:

  • 在线特征:标识1
  • 离线特征:标识2
  • 在线+离线:标识3(同时勾选在线、离线,3=1+2)

筛选查询在线特征时,sql查询条件如下:

1
where feature_mode in (1,3)

筛选查询在线特征、离线特征时,sql查询条件如下:

1
where feature_mode in (1,2,3)

标识3作为固定条件统一加入查询范围,因为3可以代表全集。

现在需要新加入一种新的特征类别:分单特征。

创建新的特征时,会出现以下情况:

在线特征 离线特征 分单特征
情形1
情形2
情形3
情形4
情形5
情形6
情形7

$$
C_3^1+C_3^2+C_3^3=2^3-1
$$

按照原有的设计,分单特征标识为4,数据库存储如下:

  • 在线特征:标识1
  • 离线特征:标识2
  • 在线+离线:标识3(同时勾选在线、离线,3=1+2)
  • 分单特征:标识4
  • 在线+分单:标识5(5=1+4)
  • 离线+分单:标识6(6=2+4)
  • 在线+离线+分单:标识7(7=1+2+4)

查询分单特征时,sql查询条件如下:

1
where feature_mode in (4,3)

会筛选出在线和离线的特征,原有的固定拼接条件已不再适用。

方案设计

数据存储

多维特征的存储仍然使用求和的方式,用二进制表示如下:

在线特征 离线特征 分单特征 十进制 二进制
情形1 1 1
情形2 2 10
情形3 4 100
情形4 3 11
情形5 5 101
情形6 6 110
情形7 7 111
数据查询

观察到,在线特征可以表示为二进制的第一位(最低位),离线特征可以表示为第二位,分单特征可以表示为第三位。

于是,sql查询条件可以设计:

  • 查在线特征
1
where feature_mode & 1 = 1

匹配十进制1、3、5、7,覆盖情形1、情形4、情形5、情形7。

  • 查在线和分单特征
1
where ((feature_mode & 1) = 1) OR ((feature_mode & 4) = 4)

匹配十进制1、3、4、5、6、7,覆盖情形1、情形3、情形4、情形5、情形6、情形7。

总结

通过二进制存储+位运算查询的方式,对于N种特征类别,可以进行2^n-1种组合查询。