我们有一个包含带标签的实体的数据集。每个标记都是一个字符串,每个实体最多可以有3个与之关联的标记。
我们希望实现一个索引,以便快速查询哪些标签最常与一组给定标签共同出现。例如,我可能有以下实体:
Entity 1 - tags A, B, Z
Entity 2 - tags B, C, E
Entity 3 - tags A, B, Y
Entity 4 - tags A, E, F
与A最常出现的标签是B(2次)。与A和B最常出现的标签是Y和Z(每次一次)。
我们的数据集相当小(约2000个项目),它所代表的2000维空间非常稀疏,所以毫无疑问,只需按标签对数据进行分区,然后枚举实体以找到最常见的标签。但是,如果有一个特定的索引类型可以有效地处理大型数据集的这类问题,我很感兴趣。
答案 0 :(得分:0)
假设:
1)标签在实体中按字母顺序排列。
2)一个实体可以包含至少1个标签和最多3个标签(您实际上已经说过)
3)实体是非唯一的
4)标签是唯一的
5)共现可以是2个标签或3个(如上所述)
6)实体第二和第三位置的标签对是您希望索引的共现
7)您可以使用RDBMS,例如MySQL的
两个表 - 实体和标签。请参阅下面的MySQL语法表创建语句。
标签上有唯一的索引。
实体由2个多列(或连接)索引编制索引,以便您可以从左向右搜索:例如on(tag1),或(tag1 AND tag2),或(tag1 AND tag2 AND tag3)或(tag2和tag3)。请参阅:https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html
中的说明多列索引允许您使用以下查询快速解决所有同现问题:
SELECT * FROM entity
WHERE tag1='A'
AND tag2='B'
AND tag3='C';
SELECT count(*) AS count, tag2, tag3 FROM entity
GROUP BY tag2, tag3
ORDER BY count DESC;
CREATE TABLE entity (
entity_name CHAR(30) NOT NULL,
tag1 CHAR(30) NOT NULL,
tag2 CHAR(30) NULL,
tag3 CHAR(30) NULL,
PRIMARY KEY (entity_name),
INDEX tags (tag1, tag2, tag3),
INDEX tags2 (tag2, tag3)
);
CREATE TABLE tag (
tag CHAR(30) NOT NULL
PRIMARY KEY (tag)
);
答案 1 :(得分:0)
一个记录给出3对[(1,2),(2,3),(1,3)]一个元素和3对[((1,2),3),((1,3) ,2),((2,3),1)]有两个元素。总共只有6双。 如果你想快速选择,你可以用计数器保存它。
在一般情况下(N(标签)> 3,N =?),我想,您可以构建标签的树:所有标签按名称排序,每个节点 - 一个标签,边缘意味着您有两个标签的实体,重量 - 反击。 所以你需要O(N)迭代从你的请求的根到最后一个标签并找到min(weight)(N - tag的查询链大小)。并且O(N)到过去的新标签链,如果你从根标签开始(N - 标签的链大小的插入)。
您在RustyB的回答中看到的更传统的方式,为您使用多列索引。请注意,在大多数情况下,将字符串(或varchars)存储在RDBMS中是非常有效的(如果它可能是使用dirs的数字),因为如果不需要总是读取带有标记的行,则读/写字符串很慢。对于这个任务,我认为,对于所有数据库都是如此,因为整数值的索引和整数的比较通常比字符更快。