【发布时间】:2010-02-15 23:04:36
【问题描述】:
基本上,我想为条目设置一个标记系统,例如堆栈溢出,并尝试规划基于相关性的搜索如何工作。我希望有一个选项可以为相关条目部分提取类似的标记条目。现在我使用两个表作为标签,每个唯一标签的表和连接表。我正在尝试考虑这是否可以生成共享相似标签的条目列表。
如果有人有任何想法或链接到我可以阅读的文章以使我的大脑朝着正确的方向前进,那将是惊人的。谢谢!
【问题讨论】:
基本上,我想为条目设置一个标记系统,例如堆栈溢出,并尝试规划基于相关性的搜索如何工作。我希望有一个选项可以为相关条目部分提取类似的标记条目。现在我使用两个表作为标签,每个唯一标签的表和连接表。我正在尝试考虑这是否可以生成共享相似标签的条目列表。
如果有人有任何想法或链接到我可以阅读的文章以使我的大脑朝着正确的方向前进,那将是惊人的。谢谢!
【问题讨论】:
在实体表中再添加一个字段:tags。用逗号分隔的标签字符串,以防止选择实体列表的另外 2 个连接。
【讨论】:
也许您可以有一个单独的表来存储相关条目。
EntryId RelatedEntryId
然后您可以让 CRON 作业定期重新计算关系并更新表。这比尝试动态计算这些关系要便宜。
【讨论】:
您需要跟踪一个标签链接到另一个标签的频率。比如说,“php”和“mysql”共享 50 篇文章(或任何被标记的主要内容),而“php”和“sql-server”可能有 3 个,而“php”和“apache”有 25 个。所以给定“php”,您希望按该顺序返回“mysql”和“apache”(可能让“sql-server”落到路边)。
这绝不是理想的,只是大声思考(并且有点扩展斯蒂芬克的答案,现在我看到了):
CREATE TABLE tag_relations (
tag_id int unsigned not null,
related_tag_id int unsigned not null,
relation_count smallint unsigned not null,
PRIMARY KEY (tag_id, related_tag_id),
KEY relation_count (relation_count)
);
然后对于与文章相关的每个唯一标签,循环遍历所有其他标签和 INSERT / UPDATE,将关系计数增加 1。这意味着 ("php", "mysql") 和 ("mysql", "php")是要维护的两个完全不同的关系,但是如果不深入挖掘我可能已经忘记的搜索概念,它仍然会起作用。如果某物有 10 多个标签,更新将非常慢(可能像 stephenc 建议的那样将其传递给 cron),但这样搜索会更容易。像这样简单明了:
SELECT related_tag_id, COUNT(relation_count) AS total_relations
FROM tag_relations
WHERE tag_id IN ([list,of,tag,IDs,to,compare])
// AND tag_id NOT IN ([list,of,tag,IDs,to,compare]) -- probably
GROUP BY related_tag_id
ORDER BY total_relations DESC
至少比必须检查tag_id 和related_tag_id 并通过一堆子查询来总结它们要容易得多。加入您的标签表以获取实际的标签名并设置好。
因此,如果您正在查找“php”和“mysql”,并且“apache”通常与两者相关,那么它会靠近顶部,因为它会计算和加权每个常见关系。不过,它不会严格将其限制为公共链接,因此请添加 HAVING total_relations >= x(x 是任意截止)和/或只是常规的 LIMIT x 以保持相关性。
(注意:在认为这甚至有点用之前,请先研究一下这个问题 - 我确信那里有一些已知的算法比它聪明 100 倍,我只是不记得了。)
PHPro.org 也有一个good writeup,使用了类似的想法。
【讨论】: