标签,云和search的最佳数据架构(如StackOverflow)?
我很想知道Stack Overflow的标记和search是如何构build的,因为它似乎工作得很好。
什么是一个好的数据库/search模式,如果我想要做以下所有的事情:
- 在各种实体上存储标签(如何标准化?即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
我现在正在为我提到的每个项目做的事情:
- 在数据库中,有3个表格:Entity,Tag,Entity_Tag。 我使用DB来:
- build立整个网站的标签云
- 浏览标签(即像SO的/questions/tagged/ASP.NETurl)
- 为了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命中数据库
- 标签被连接成一个由Lucene索引的TagString
- 还没有这样做,但我想我可能会尝试find一种方法来从Lucene中的TagString构build标签云,而不是采取另一个数据库命中
- 还没有做到这一点,但我可能会在数据库中存储TagString,以便我可以显示一个实体的标签列表,而不必再做2个连接。
这意味着每当一个实体的标签被修改,我必须:
- 插入任何不存在的新标签
- 从EntityTag表中插入/删除
- 更新Entity.TagString
- 更新实体的Lucene索引
鉴于读写比在我的应用程序中是非常大的,我想我可以这样做。 唯一真正耗时的部分是Lucene索引,因为Lucene只能从它的索引中插入和删除 ,所以我必须重新索引整个实体以更新TagString。 我对此并不感到兴奋,但是我认为如果我在后台线程中这样做,那就没问题了。
时间会告诉…
我不知道它们是否合格,但是DotNetKicks和Kigg都是开源的digg克隆实现。 你可以看看他们如何做标签和search。
我最好的猜测没有很多的考虑:)
- 我从来不喜欢将多个值序列化为单个字段的想法,因此存储在一个字段中的分隔string不会吸引我…可能适用于具有树的相邻path,但这些path总是有序的,标记不必是。 这看起来像是会征税LIKE操作员的工作,你可能会find它们。
所以我最初的可能是实体 – > EntityTag < – 标签。
-
这种方法使得通过标签查找项目变得非常简单,通过EntityTag连接回来,称之为一天。
-
您需要在此处进行辅助操作,以便为结果集select不同的标记。 所以a。)拉结果集,b。)标准化标签空间。 我认为不pipe第一个答案是什么,即使将标签填充到一个字段中仍然会产生重复的标签(而且你必须反序列化它们来执行这个操作 – 所以更多的工作,完全关系的另一个参数方法)。
-
仍然容易。 这里是序列化方法更好的一个领域。 不需要join子标签,它就在实体中。 也就是说,通过两个表连接拉出0..n标签对我来说似乎不是太具有挑战性。 如果你正在谈论性能考虑,首先build立规范,然后通过caching或denorm优化。
另一个select是“做两个”。 这感觉就像是一个过早的优化,但是你可以做完整的规范化的方法来支持任何以标签为中心的操作,并且在持续存在一个非规范化的版本的情况下序列化。 如果没有完全覆盖的话,还有一些工作可能会失去同步,但如果在用例中完全正常化的方式存在真正的局限性,那么两者都是最好的。
Lucene也很有趣,你可以在索引IIRC中声明特定的元数据,所以你也可以用这种方式来利用标签search。 我的怀疑是,如果你在这条路上走得太远,那么你最终会在数据库中存储的内容与索引之间产生一些断开。 我可以赞成地说Lucene,它的function非常强大,易于使用 – 我相信.Text使用它来实现searchfunction,它在切换到社区服务器之前支持所有的weblogs.asp.net。 如果MSSQL不在图片/足够的位置,我会坚持使用全文search来解决数据库中的标签问题。