2008-10-24 87 views
38

我很想知道Stack Overflow的标记和搜索是如何构建的,因为它似乎工作得很好。用于标记,云和搜索的最佳数据体系结构(如StackOverflow)?

,如果我想要做以下所有的是一个良好的数据库/搜索模式:

  1. 存储标签上的各种实体,(如何归一化即实体,标签和Entity_Tag表?)
    • 搜索和特定代码
    • 建立了适用于特定搜索结果的所有标签的标签云项目集
    • 如何显示标签列表对于搜索结果中的每个项目?

或许是有意义的标签存储在规范化的形式,也可作为的#2,#4,#也许3所指的空间分隔的字符串。思考?

我听说它说Stack Overflow使用Lucene进行搜索。真的吗?我听过一些讨论SQL优化的播客,但没有提到Lucene。如果他们确实使用Lucene,我想知道搜索结果有多少来自Lucene,并且“下钻”标签云是否来自Lucene。

回答

5

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

我没有很多的酝酿最佳猜测:)

  1. 我从来没有像序列化多个值到一个单一领域的想法,存储在一个字段,以便分隔字符串不吸引我...可能适用于具有树的邻接路径,但这些路径总是有序的而标签不需要。这看起来好像会征税LIKE操作员的工作,你可能会找到它们。

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

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

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

  3. 还是很容易的。以下是序列化方法效果更好的一个领域。无需加入子标签,它就在实体中。也就是说,通过两个表连接拉出0..n标签对我来说似乎不是太具有挑战性。如果你正在讨论perf的考虑事项,首先将它构建为规范化,然后通过缓存或denorm进行优化。

另一种选择是“同时做”。这感觉就像是一种过早的优化,但是您可以采用完全标准化的方法来支持任何以标签为中心的操作,并在持续存在序列化后在实体中拥有非标准化版本。如果还没有完全覆盖,还有一些工作可能会失去同步,但如果在用例中完全标准化的方式存在真正的限制,那么两者都是最好的。

Lucene也很有趣,你可以在索引IIRC中声明特定的元数据,所以你也可以用这种方式来利用标签搜索。我的怀疑是,如果你在这条路上走得太远,那么你最终会在数据库中存储的内容与某个时刻的索引之间断开连接。我可以赞同Lucene的说法,它的功能非常强大且易于使用 - 我相信.Text将其用于搜索功能,并且在它切换到社区服务器之前支持所有的weblogs.asp.net。如果MSSQL不在图片/足够的范围内,我会坚持使用全文搜索来解决数据库中的标签问题。

57

哇,我刚刚写了一个大帖子,因此窒息并挂在它上面,当我点击后退按钮重新提交时,标记编辑器为空。 aaargh。

所以在这里,我又来了......

关于堆栈溢出,事实证明,他们使用SQL server 2005 full text search

关于通过@Grant推荐OS项目:

  • * DotNetKicks使用DB标记和Lucene的全文搜索。似乎没有办法将全文搜索与标签搜索相结合
  • Kigg对于搜索和标签查询都使用Linq-to-SQL。这两个查询都加入了Stories-> StoryTags-> Tags。
  • 这两个项目有3餐桌的标记,因为大家一般似乎建议

我也发现了所以一些其他问题,我已经错过前:

我正在为我提到的每个项目做些什么:

  1. 在DB中,有3个表:Entity,Tag,Entity_Tag。我用的是DB到:
    • 构建整个网站的标签云
    • 根据标签浏览(即网址,像这样的/questions/tagged/ASP.NET
  2. 对于搜索我利用Lucene + NHibernate。搜索
    • 标签是concat'd到由Lucene的索引的TagString
      • 所以我有Lucene的查询引擎的全功率(AND/OR/NOT查询)
      • 我可以搜索文字过滤器由标签同时
      • Lucene的分析合并的话更好的标签搜索(即标签搜索“测试”也将找到的东西标记为“测试”)
    • Lucene的返回一个潜在的巨大的结果集,这是我分页到20个结果
    • 然后NHibernate的加载凭身份证形成的实体,无论是从数据库或实体缓存
    • 所以这是完全有可能在0点击一个搜索结果到DB
  3. 不这样做,但我想我可能会尝试找到一种方法,从在Lucene中的TagString建标签云,而不是采取其他DB命中
  4. 没有这样做但也可以,但我可能会将TagString存储在数据库中,以便我可以显示实体的标记列表而无需再进行2次连接。

这意味着只要一个实体的代码修改,我必须:

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

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

时间会告诉我们......

+0

着upmod这篇文章足以 – Shawn 2009-01-03 21:16:48

相关问题