标签,云和search的最佳数据架构(如StackOverflow)?

我很想知道Stack Overflow的标记和search是如何构build的,因为它似乎工作得很好。

什么是一个好的数据库/search模式,如果我想要做以下所有的事情:

  1. 在各种实体上存储标签(如何标准化?即Entity,Tag和Entity_Tag表?)
    • search具有特定标签的项目
    • 构build适用于特定search结果集的所有标签的标签云
    • 如何在search结果中显示每个项目的标签列表?

将标签存储为标准化的forms也许是有意义的,但也可以将其用作#2,#4,也许是#3的空格分隔的string。 思考?

我听说过,Stack Overflow使用Lucene进行search。 真的吗? 我听说过几个讨论SQL优化的播客,但没有提到Lucene。 如果他们使用Lucene,我想知道有多lesssearch结果来自Lucene,以及“向下钻取”标签云是否来自Lucene。

哇,我只是写了一个大的post,因此ch咽,挂在上面,当我打我的后退button重新提交,标记编辑器是空的。 aaargh。

所以在这里我再去…

关于堆栈溢出,事实certificate,他们使用SQL Server 2005全文search 。

关于@Grant推荐的操作系统项目:

  • * DotNetKicks使用数据库进行标记,并使用Lucene进行全文search。 似乎没有办法将全文search与标签search结合起来
  • Kigg使用Linq-to-SQL进行search和标签查询。 这两个查询都join了Stories-> StoryTags-> Tags。
  • 这两个项目都有一个3表的方法来标记每个人通常似乎build议

我还发现了一些我以前错过的其他问题:

  • 你如何推荐实施标签或标签?
  • 如何构build可search性数据?
  • 数据库标签devise

我现在正在为我提到的每个项目做的事情:

  1. 在数据库中,有3个表格:Entity,Tag,Entity_Tag。 我使用DB来:
    • build立整个网站的标签云
    • 浏览标签(即像SO的/questions/tagged/ASP.NETurl)
  2. 为了search我使用Lucene + NHibernate.Search
    • 标签被连接成一个由Lucene索引的TagString
      • 所以我有了Lucene查询引擎的全部function(AND / OR / NOT查询)
      • 我可以search文本, 通过标签同时过滤
      • Lucene分析器合并单词以获得更好的标签search(即,标签search“test”也会find标签为“testing”的东西)
    • Lucene返回一个潜在的巨大的结果集,我分页到20个结果
    • 然后NHibernate从数据库或实体caching中加载Id的结果实体
    • 所以这是完全可能的,search结果0命中数据库
  3. 还没有这样做,但我想我可能会尝试find一种方法来从Lucene中的TagString构build标签云,而不是采取另一个数据库命中
  4. 还没有做到这一点,但我可能会在数据库中存储TagString,以便我可以显示一个实体的标签列表,而不必再做2个连接。

这意味着每当一个实体的标签被修改,我必须:

  • 插入任何不存在的新标签
  • 从EntityTag表中插入/删除
  • 更新Entity.TagString
  • 更新实体的Lucene索引

鉴于读写比在我的应用程序中是非常大的,我想我可以这样做。 唯一真正耗时的部分是Lucene索引,因为Lucene只能从它的索引中插入删除 ,所以我必须重新索引整个实体以更新TagString。 我对此并不感到兴奋,但是我认为如果我在后台线程中这样做,那就没问题了。

时间会告诉…

我不知道它们是否合格,但是DotNetKicks和Kigg都是开源的digg克隆实现。 你可以看看他们如何做标签和search。

我最好的猜测没有很多的考虑:)

  1. 我从来不喜欢将多个值序列化为单个字段的想法,因此存储在一个字段中的分隔string不会吸引我…可能适用于具有树的相邻path,但这些path总是有序的,标记不必是。 这看起来像是会征税LIKE操作员的工作,你可能会find它们。

所以我最初的可能是实体 – > EntityTag < – 标签。

  1. 这种方法使得通过标签查找项目变得非常简单,通过EntityTag连接回来,称之为一天。

  2. 您需要在此处进行辅助操作,以便为结果集select不同的标记。 所以a。)拉结果集,b。)标准化标签空间。 我认为不pipe第一个答案是什么,即使将标签填充到一个字段中仍然会产生重复的标签(而且你必须反序列化它们来执行这个操作 – 所以更多的工作,完全关系的另一个参数方法)。

  3. 仍然容易。 这里是序列化方法更好的一个领域。 不需要join子标签,它就在实体中。 也就是说,通过两个表连接拉出0..n标签对我来说似乎不是太具有挑战性。 如果你正在谈论性能考虑,首先build立规范,然后通过caching或denorm优化。

另一个select是“做两个”。 这感觉就像是一个过早的优化,但是你可以做完整的规范化的方法来支持任何以标签为中心的操作,并且在持续存在一个非规范化的版本的情况下序列化。 如果没有完全覆盖的话,还有一些工作可能会失去同步,但如果在用例中完全正常化的方式存在真正的局限性,那么两者都是最好的。

Lucene也很有趣,你可以在索引IIRC中声明特定的元数据,所以你也可以用这种方式来利用标签search。 我的怀疑是,如果你在这条路上走得太远,那么你最终会在数据库中存储的内容与索引之间产生一些断开。 我可以赞成地说Lucene,它的function非常强大,易于使用 – 我相信.Text使用它来实现searchfunction,它在切换到社区服务器之前支持所有的weblogs.asp.net。 如果MSSQL不在图片/足够的位置,我会坚持使用全文search来解决数据库中的标签问题。