【问题标题】:Optimal data architecture for tagging, clouds, and searching (like StackOverflow)?用于标记、云和搜索的最佳数据架构(如 StackOverflow)?
【发布时间】:2010-09-19 02:04:27
【问题描述】:

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

如果我想做以下所有事情,什么是好的数据库/搜索模型:

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

也许以规范化的形式存储标签是有意义的,但也可以作为空格分隔的字符串用于#2、#4,也许还有#3。想法?

我听说 Stack Overflow 使用 Lucene 进行搜索。真的吗?我听过一些讨论 SQL 优化的播客,但没有关于 Lucene 的内容。如果他们确实使用 Lucene,我想知道搜索结果中有多少来自 Lucene,以及“向下钻取”标签云是否来自 Lucene。

【问题讨论】:

    标签: database-design tags full-text-search tag-cloud


    【解决方案1】:

    哇,我刚刚写了一篇大文章,然后就哽咽着挂在上面,当我点击后退按钮重新提交时,标记编辑器是空的。啊。

    所以我又来了……

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

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

    • *DotNetKicks 使用 DB 进行标记,使用 Lucene 进行全文搜索。似乎没有办法将全文搜索与标签搜索结合起来
    • Kigg 使用 Linq-to-SQL 进行搜索和标记查询。两个查询都加入 Stories->StoryTags->Tags。
    • 这两个项目都采用 3 表方法进行标记,似乎每个人都普遍推荐

    我还发现了一些我之前错过的关于 SO 的其他问题:

    我目前对我提到的每个项目都在做什么:

    1. 在 DB 中,有 3 个表:Entity、Tag、Entity_Tag。我使用数据库:
      • 构建站点范围的标签云
      • 按标签浏览(即像 SO 的 /questions/tagged/ASP.NET 这样的 URL)
    2. 对于搜索,我使用 Lucene + NHibernate.Search
      • 标签被连接成一个由 Lucene 索引的 TagString
        • 所以我拥有 Lucene 查询引擎的全部功能(AND / OR / NOT 查询)
        • 我可以同时搜索文本标签过滤
        • Lucene 分析器会合并单词以便更好地进行标签搜索(即“test”的标签搜索也会找到标记为“testing”的内容)
      • Lucene 返回一个潜在的巨大结果集,我将其分页为 20 个结果
      • 然后 NHibernate 按 Id 从数据库或实体缓存中加载结果实体
      • 因此,搜索结果完全有可能对 DB 产生 0 次命中
    3. 目前还没有这样做,但我想我可能会尝试找到一种方法来从 Lucene 中的 TagString 构建标签云,而不是再次点击数据库
    4. 还没有这样做,但我可能会将 TagString 存储在数据库中,这样我就可以显示实体的标记列表,而无需再进行 2 次连接。

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

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

    鉴于在我的应用程序中读取与写入的比率非常大,我认为我可以接受。唯一真正耗时的部分是 Lucene 索引,因为 Lucene 只能从其索引中插入删除,所以我必须重新索引整个实体才能更新标记字符串。我对此并不感到兴奋,但我认为如果我在后台线程中执行此操作,那就没问题了。

    时间会证明一切的......

    【讨论】:

    • 此答案中的第一个链接(“SQL server 2005 全文搜索”)似乎不再起作用?
    • 更新后的链接可能是:meta.stackexchange.com/questions/19548/…
    • 回顾一下,Winston,感谢您跟进您的方法。
    【解决方案2】:

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

    我最好的猜测没有经过深思熟虑:)

    1. 我从不喜欢将多个值序列化到一个字段中的想法,因此存储在一个字段中的分隔字符串对我没有吸引力...可能适用于具有树的邻接路径,但它们始终是有序的,标签不需要是。这似乎会使您为找到它们而可能做的 LIKE 操作员工作增加负担。

    所以我最初的想法可能是 Entity -> EntityTag

    1. 这种方法使通过 Tag 查找项目变得非常容易,通过 EntityTag 重新加入,收工。

    2. 您需要在此处进行辅助操作来为结果集选择不同的标签。所以 a.) 拉取结果集,b.) 规范化标签空间。我认为无论#1 的答案是什么,你都会这样做——即使将标签填充到一个字段中仍然会产生重复的标签(并且你必须对它们进行反序列化才能执行此操作——因此需要更多的工作,这是完全关系的另一个论点接近)。

    3. 还是很简单的。这是序列化方法效果更好的一个领域。无需加入子标签,它就在实体中。也就是说,通过两个表连接提取 0..n 个标签对我来说似乎并没有太大的挑战性。如果您在谈论性能方面的考虑,请先对其进行规范化构建,然后通过缓存或 denorm 进行优化。

    另一个选项是“两者都做”。这感觉像是过早的优化,但您可以使用完全规范化的方法来支持任何以标签为中心的操作并在持久化后序列化以在实体中拥有非规范化版本。更多的工作,如果没有完全覆盖,可能会出现不同步的情况,但如果在您的用例中完全规范化的方式存在真正的限制,则两全其美。

    Lucene 也很有趣,您可以在索引 IIRC 中声明特定的元数据,因此您也可以通过这种方式利用标签搜索。我的怀疑是,如果你在这条路上走得太远,那么你最终会在数据库中存储的内容与索引之间出现一些断开连接。我可以说 Lucene,它功能强大且易于使用——我相信 .Text 使用它是因为它的搜索功能,并且在切换到社区服务器之前它支持所有 weblogs.asp.net。如果MSSQL不在图片中/足够,我会坚持全文搜索,解决数据库imo中的标签问题。

    【讨论】:

      猜你喜欢
      • 2011-07-02
      • 1970-01-01
      • 2011-03-28
      • 2013-03-13
      • 2015-11-16
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 2011-01-18
      相关资源
      最近更新 更多