我很想知道Stack Overflow的标记和搜索是如何构建的,因为它看起来效果很好.
如果我想要执行以下所有操作,那么什么是良好的数据库/搜索模型:
在各种实体上存储标签,(如何规范化?即实体,标签和Entity_Tag表?)
搜索具有特定标签的项目
构建适用于特定搜索结果集的所有标记的标记云
如何在搜索结果中显示每个项目的标签列表?
也许以标准化的形式存储标签是有意义的,但也可以作为空格分隔的字符串用于#2,#4和#3的目的.思考?
我听说它说Stack Overflow使用Lucene进行搜索.真的吗?我听过几个关于SQL优化的播客,但没有关于Lucene的内容.如果他们确实使用Lucene,我想知道有多少搜索结果来自Lucene,以及"钻取"标签云是否来自Lucene.
哇我刚刚写了一个大帖子,因此被阻塞并挂在上面,当我按下我的后退按钮重新提交时,标记编辑器是空的.aaargh.
所以我再来一次......
关于Stack Overflow,事实证明他们使用SQL Server 2005全文搜索.
关于@Grant推荐的操作系统项目:
*DotNetKicks使用DB进行标记,使用Lucene进行全文搜索.似乎无法将全文搜索与标签搜索相结合
Kigg使用Linq-to-SQL进行搜索和标记查询.两个查询都加入了Stories-> StoryTags-> Tags.
两个项目都有一个3表的标记方法,因为每个人似乎都建议
我还发现了一些我以前错过的其他问题:
您如何推荐实施标签或标签?
如何构建数据以进行可搜索性?
标记数据库设计
我目前正在为我提到的每个项目做些什么:
在DB中,有3个表:Entity,Tag,Entity_Tag.我使用DB来:
构建站点范围的标签云
按标签浏览(即SO的/questions/tagged/ASP.NET等网址)
对于搜索,我使用Lucene + NHibernate.Search
标签被连接到由Lucene索引的TagString中
所以我拥有Lucene查询引擎的全部功能(AND/OR/NOT查询)
我可以搜索文本并同时按标签过滤
Lucene分析器合并单词以获得更好的标签搜索(即标签搜索"test"也会找到标记为"testing"的内容)
Lucene返回了一个潜在的巨大结果集,我将其分为20个结果
然后NHibernate通过Id从DB或Entity缓存加载结果Entities
因此,搜索结果完全有可能导致数据库的0次点击
还没有这样做,但我想我可能会试图找到一种方法来构建Lucene的TagString中的标签云,而不是采取另一个数据库命中
还没有这样做,但我可能会将TagString存储在数据库中,以便我可以显示实体的标签列表,而无需再进行2次连接.
这意味着每当修改实体的标签时,我必须:
插入任何尚不存在的新标签
从EntityTag表中插入/删除
更新Entity.TagString
更新实体的Lucene索引
鉴于我的应用程序中读取与写入的比例非常大,我认为我对此很满意.唯一真正耗时的部分是Lucene索引,因为Lucene只能从其索引中插入和删除,所以我必须重新索引整个实体才能更新TagString.我对此并不感到兴奋,但我认为如果我在后台线程中这样做,那就没问题了.
时间会告诉......
我不知道他们是否符合最佳条件,但DotNetKicks和Kigg都是开源的digg克隆实现.你可以看看他们是如何做标签和搜索的.
我最好的猜测没有经过深思熟虑:)
我从不喜欢将多个值序列化到单个字段中的想法,因此存储在一个字段中的分隔字符串对我不具吸引力...可能适用于带树的邻接路径,但总是有序且标签不需要.这似乎会对LIKE运营商的工作征税,以便找到它们.
所以我最初的看法可能是Entity - > EntityTag < - Tag.
这种方法可以很容易地通过Tag查找项目,通过EntityTag加入,一天调用它.
您需要在此处进行辅助操作,以便为结果集选择不同的标记.所以a.)拉结果集,b.)标准化标签空间.我认为无论答案是什么,你都会这样做 - 即使将标签填充到一个字段中仍然会产生重复的标签(并且你必须反序列化它们才能执行这个操作 - 所以更多的工作,完全关系的另一个论点方法).
还很容易.这是序列化方法更好地工作的一个领域.无需加入子标签,它就在实体中.也就是说,通过两个表连接拉出0..n标签对我来说似乎并不太具有挑战性.如果您正在讨论性能考虑因素,请首先将其标准化,然后通过缓存或变性进行优化.
另一种选择是"两者兼顾".这感觉就像是一个过早的优化,但您可以执行完全规范化的方法来支持任何以标记为中心的操作,并在持久化时序列化以在实体中具有非规范化版本.更多的工作,如果没有完全覆盖,有些可能会失去同步,但如果在用例中完全规范化的方式存在实际限制,那么这两个方面都是最好的.
Lucene也很有趣,您可以在索引IIRC中声明特定元数据,因此您也可以通过这种方式利用标记搜索.我的怀疑是,如果你走这条路太远,那么你最终会在数据库中存储的内容和某个时刻的索引之间断开连接.我可以对Lucene赞不绝口,它非常强大且易于使用 - 我相信.Text使用它的搜索功能,并且在切换到社区服务器之前支持所有weblogs.asp.net.如果MSSQL不在图片中,我会坚持使用全文搜索/解决数据库imo中的标记问题.