Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

标签模式分类与“相关文章”的查询

  现在的数据分类都流行使用标签模式的,这种模式比传统的分类树模式模式灵活很多。一个对象可以有多个标签,而传统的分类树一个对象只能在一个叶节点上。假如有一篇文章是关于PHP和JavaScript的,如果用分类树模式就不知道应该把它放在哪个分类下。所以,分类不仅仅是树那么简单,还涉及了图形结构。因此引入了标签模式,这样就可以同时给一篇文章添加“PHP”和“JavaScript”这两个标签来解决问题。
  标签模式在数据库中的储存方式有很多种,可以参考图形结构的数据来储存。不过我使用了最简单的。建立一个存放标签的表来存放所有标签,然后直接在文章表中添加字符串字段来储存标签集合(用逗号隔开)。这种做法的效率虽然不是高效的,但是耦合度低。也许我这句话没多少份量,但是项目一旦开始运营就会明白耦合度低是多么重要了。
  现在有这样的两个表,

  它们分别名为article和taglist,现在要做的是查询ID为0的文章的相关文章。第一步是把用ID为0的文章的标签逐个取出;第二步查询所有文章,并记录每篇文章的标签字段中包含第一步中取出的标签集合中标签的个数。第三步是按第二部得到的个数来作为相关性排序的依据。那么我们就要构造一个SQL语句
select id,title,count(id) as cnt
from article,(
       select tag 
       from taglist,article
       where id=0 and 
             find_in_set(tag,tags)
     )temp #第一步的查询结果构成的临时表
where id!=0 and #排除自己
      find_in_set(tag,tags) #第二步的查询条件
group by id
order by cnt desc;
  这个SQL语句就可以查询到相关的文章,并按相关性排序了。但是这个SQL会无视掉不存在关键词相同的文章,也就是它觉得“没有相关性”的文章。而且,并不是所有标签的权重都是相同的,比如有两篇文章都包含“PHP”标签的情况和有两篇文章都包含“PHP效率”的情况,显然后者更精确,所以它的权重高。既然有了权重这么一说,那么计算文章相关程度的就应该使用加权平局数。而且权重那个这个字段可以直接在taglist表中添加。但是权重并不容易计算,所以我们使用简单的办法来得到权重,那就是标签密度。一个标签被越多的文章使用,那么它的权重就应该越低。现在我们扩展一下上面的两张表。

  在比较两篇文章的关联程度时候,当然是相同的标签越多越好,相同标签的权重越高越好。但是这两个条件独立的话它们是冲突的,假如A文章和B、C文章做比较,B包含了3个底权重标签,而C包含了1个高权重标签,这种情况的判断就很纠结。所以我们需要把这个两个条件归一化,用一个式子。匹配标签权重的和除以匹配的标签数量,这个式子得到的是匹配标签的平均权重。一般用这个式子就可以了,如果需要更复杂的关联程度计算也可以用其他式子,或者在这个基础上做微调。之前那个查询语句如果没有关联文章就不会返回记录。这种情况如果显示到网页上就非常难看。实际应用中,文章查询通常需要固定输出条数来让页面更饱满,即使没有相关性也可以添加一些记录出来充数。
  下面是应用了权重的查询语句: select id,title,sum(density*e)/sum(e) as o
from (
  select id,title,density,
         find_in_set(tag,tags)!=0 as e
  from article,(
         select tag,density
         from taglist,article
         where id=0 and 
               find_in_set(tag,tags)
       )temp
  where id!=0
)temp
group by id
order by sum(e)=0,o
  这个语句就是把原来的语句的were部分放到返回字段中,然后把整个查询放入一个临时表,最后再查询一次这个临时表。这样就可以查询出不包含查询标签的数据了,比如查询ID为0的文章的时候,ID为7、8的数据也能被查询出,只是排序在最后而已。
网名:
34.203.213.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^