我需要为某些数据集创建一个匹配查找器系统,如下所示:
有一组对象,每个对象都由字符串ObjectID
标识。
每个对象都有N个属性P i 。每个属性值都是一个字符串。
N = 3的数据库示例(在现实生活中N = 8)。
ObjectID: P1 P2 P3 -------------------------------- APPLE: RED ROUND FRUIT ORANGE: ORANGE ROUND FRUIT CARROT: RED LONG VEGETABLE
系统必须返回ObjectID
的集合,匹配对象属性的给定查询。在查询中,用户必须指定所有属性值。或者,对于查询中的部分或全部属性,用户可以指定“通配符”*
,这意味着任何属性值都符合条件。
示例查询:
P1 P2 P3 => Result ------------------------------------ * ROUND FRUIT => APPLE, ORANGE RED LONG VEGETABLE => CARROT RED * * => CARROT, APPLE
所有这些都是用SQL完成的。
问题是:有没有一种巧妙的方法可以用Redis做到这一点?
请注意,我对基于Redis的解决方案感兴趣,专门用于自我教育;对于这个特殊问题,其他数据库是非正式的。
更新:每个P i 和应用程序端过滤的明确ObjectID
列表的简单解决方案对我来说看起来不够整洁: - )
答案 0 :(得分:7)
你在这里要做的是倒排索引。
对于每列,让它映射到“set”。然后,您可以将这些集相交以获得结果。
因此,APPLE: RED ROUND FRUIT
将映射到以下插入内容:
SADD p1:RED APPLE
SADD p2:ROUND APPLE
SADD p3:FRUIT APPLE
然后,假设我要查询* ROUND FRUIT
,我会这样做:
SINTER p2:ROUND p3:FRUIT
此命令采用p2:ROUND
集和p3:FRUIT
集中的项目的交集。这将返回ROUND
和FRUIT
的所有项目,而不是关注p1
的内容。
其他一些例子:
SMEMBERS p1:GREEN
SINTER p1:RED p2:ROUND p3:FRUIT
SUNION p1:RED p1:GREEN
我的上述答案将使用一些计算能力,因为交叉操作是O(N*M)
。这是一种更加占用内存的方法,但会有更快的检索速度,因为它有效地预先计算了索引。
对于每个属性组合,请创建一个存储集合的键:
因此,APPLE: RED ROUND FRUIT
将映射到以下插入内容:
SADD RED:ROUND:FRUIT APPLE
SADD :ROUND:FRUIT APPLE
SADD RED::FRUIT APPLE
SADD RED:ROUND: APPLE
SADD RED:: APPLE
SADD :ROUND: APPLE
SADD ::FRUIT APPLE
SADD ::: APPLE
然后,要查询,只需访问相应的密钥即可。例如,* ROUND FRUIT
只是
SMEMBERS :ROUND:FRUIT
显然,当你有很多维度时,这在内存方面根本不能很好地扩展,但是检索结果会非常敏捷。