gpt4 book ai didi

sql-server-2008 - 如何使用 Lucene.NET 帮助在 Stack Overflow 等网站上实现搜索?

转载 作者:行者123 更新时间:2023-12-03 05:39:51 25 4
gpt4 key购买 nike

我有 asked a simlar question on Meta Stack Overflow ,但这专门涉及是否 Lucene.NET 用于堆栈溢出。
这里问题的目的更多是假设,如果他们使用 Lucene.NET 作为站点内搜索的基础以及 StackOverflow [SO] 等站点中的其他因素,他们会采用什么方法。
根据 Stack Overflow 博客上题为“SQL 2008 Full-Text Search Problems”的条目,有一个 表明 Lucene.NET 正在考虑在某个时候,但看起来这绝对不是 2124 2010年:

Lucene.NET is not being used for StackOverflow - we are using SQL ServerFull Text indexing. Search is an areawhere we continue to make minortweaks.


所以我的问题是,如何将 Lucene.NET 用于具有相同堆栈溢出语义的站点?
这是一些背景以及到目前为止我所做的/想到的(是的,我一直在实现其中的大部分内容,而搜索是我必须完成的最后一个方面):
技术:
  • Geoff Dalgas
  • ASP.NET MVC
  • SQL Server 2008
  • .NET 3.5

  • 当然,还有节目的主角 Lucene.NET。
    其目的还在于尽快迁移到 .NET/C# 4.0。虽然我不认为它会改变游戏规则,但应该注意。
    在进入 Lucene.NET 的各个方面之前,重要的是指出它的 SQL Server 2008 方面以及所涉及的模型。
    型号
    与 Stack Overflow 相比,该系统具有不止一种主要模型类型。这些模型的一些例子是:
  • 问题:这些是人们可以提出的问题。人们可以回复问题,就像在 StackOverflow 上一样。
  • 注意:这些是单向预测,因此与问题相反,您正在对内容进行陈述。人们无法对此发表回复。
  • 事件:这是关于实时事件的数据。它具有位置信息、日期/时间信息。

  • 关于这些模型需要注意的重要事项:
  • 它们都有一个名称/标题(文本)属性和一个正文(HTML)属性(格式无关,因为内容将被适本地解析以进行分析)。
  • 模型的每个实例在站点上都有一个唯一的 URL

  • 然后是 StackOverflow 提供的 IMO,是模型的装饰器。这些装饰器可以有不同的基数,可以是一对一或一对多:
  • 投票:锁定用户
  • 回复:可选,例如,见上面
  • 的Notes案例
  • 收藏夹:模型是否被列为用户的收藏夹?
  • 评论:(可选)
  • 标签关联:标签在单独的表中,以免为每个模型复制标签。模型和标签关联表之间有一个链接,然后从标签关联表到标签表。

  • 并且有支持标签,它们本身是模型的一对一装饰器,这些模型以相同的方式(通常通过模型 ID 类型和模型 ID):
  • 投票数:总赞成票,反对票,C# 3.0(这很重要,它将根据条目的投票确定置信度,在大多数情况下,假设威尔逊区间的下限)。

  • 回复(答案)是具有大多数模型拥有的大部分装饰器的模型,它们只是没有标题或网址,并且模型是否有回复是可选的。如果允许回复,那当然是一对多的关系。
    SQL Server 2008
    这些表几乎遵循上述模型的布局,为装饰器提供单独的表,以及一些支持表和 View 、存储过程等。
    应该注意的是,决定不使用全文搜索主要是因为它不像 Lucene.NET 那样对分数进行标准化。我愿意接受有关如何利用基于文本的搜索的建议,但我必须跨多种模型类型执行搜索,因此请记住,我需要以某种方式对分数进行标准化。
    Lucene.NET
    这是最大的问号所在。以下是我目前对 StackOverflow 功能的想法,以及我已经完成的工作和方法。
    索引
    问题/模型
    我相信每个模型都应该有一个包含唯一 id 的索引,以便根据该 id 的 Term 实例(已索引,未分析)快速查找它。
    在这方面,我考虑过让 Lucene.NET 单独分析每个问题/模型和每个回复。因此,如果有 1 个问题和 5 个答案,则该问题和每个答案将分别作为一个单元编入索引。
    这里的想法是 Lucene.NET 返回的相关性分数将更容易在以不同方式投影的模型之间进行比较(例如,没有回复的东西)。
    例如,一个问题设置主题,然后答案详细说明主题。
    对于没有回复的便条,它处理呈现主题然后对其进行详细说明的问题。
    我相信这将有助于使相关性分数彼此更相关。
    标签
    最初,我认为这些应该保存在具有多个字段的单独索引中,这些字段具有适当模型索引中文档的 id。或者,如果它太大,则有一个仅包含标签的索引和另一个维护标签索引与其所应用的问题之间关系的索引。这样,当你点击一个标签(或使用 URL 结构)时,很容易以渐进的方式看到,如果你成功了,你只需要“买入”:
  • 如果标签存在
  • 哪些问题标签与
  • 相关联
  • 问题本身

  • 然而,在实践中,使用 SQL Server 2008 根据标签查询所有项目(例如在 StackOverflow 中点击标签)非常容易。基于上面的模型,它只需要一个查询,例如:
    select
    m.Name, m.Body
    from
    Models as m
    left outer join TagAssociations as ta on
    ta.ModelTypeId = <fixed model type id> and
    ta.ModelId = m.Id
    left outer join Tags as t on t.Id = ta.TagId
    where
    t.Name = <tag>
    由于某些属性在所有模型之间共享,因此在不同模型类型/表之间执行 UNION 并产生一组一致的结果很容易。
    这将类似于 Lucene.NET 中的 Wilson Score interval(我指的是 TermQuery ,因为它是全面的,而 Lucene.NET 是 0x2518122423341 的逐行翻译)。
    在这里使用 Lucene.NET 出现的问题是排序顺序。当涉及到标签时,TermQuery 的相关性分数是无关紧要的。它是 1 或 0(它要么有,要么没有)。
    此时,置信度分数(威尔逊分数区间)开始对结果进行排序。
    这个分数可以存储在 Lucene.NET 中,但为了对这个字段的结果进行排序,它会依赖于存储在字段缓存中的值,这是我非常非常想要避免的事情。对于大量文档,字段缓存可能会变得非常大(Wilson 分数是一个 double 值,您需要为每个文档添加一个 double 值,这可以是一个大数组)。
    鉴于我可以将 SQL 语句更改为基于 Wilson 分数区间的顺序,如下所示:
    select
    m.Name, m.Body
    from
    Models as m
    left outer join TagAssociations as ta on
    ta.ModelTypeId = <fixed model type id> and
    ta.ModelId = m.Id
    left outer join Tags as t on t.Id = ta.TagId
    left outer join VoteTallyStatistics as s on
    s.ModelTypeId = ta.ModelTypeId and
    s.ModelId = ta.ModelId
    where
    t.Name = <tag>
    order by
    --- Use Id to break ties.
    s.WilsonIntervalLowerBound desc, m.Id
    使用它来处理 StackOverflow 功能“获取所有带有 标记的项目”似乎是一个简单的选择。
    回复
    本来,我以为这是在它自己的一个单独的索引中,用一个键回到问题索引中。
    我认为应该将每个模型和每个回复(如果有的话)结合起来,以便不同模型之间的相关性得分在相互比较时更加“平等”。
    这当然会使索引膨胀。我现在对此感到有些自在。
    或者,有没有办法在 Lucene.NET 中将模型和回复存储为单独的文档,然后将两者都存储并能够获得将两个文档视为一个的查询的相关性分数?如果是这样,那么这将是 理想的
    当然还有一个问题是哪些字段将被存储、索引、分析(所有操作可以是单独的操作,也可以是混合匹配)?一个指数会是多少?
    使用特殊的词干分析器/搬运工来解决拼写错误(使用 Metaphone)以及同义词(我将服务的社区中有术语,对于某些具有多种表示形式的事物有自己的俚语/术语)?
    升压
    这当然与索引有关,但我认为它值得它自己的部分。
    您是 提升 字段和/或文档吗?如果是这样,你如何提升它们?某些领域的提升是否恒定?或者是否为投票/查看/收藏/外部数据适用的字段重新计算。
    例如,在文档中,标题是否比正文得到了提升?如果是这样,您认为哪些促进因素有效?标签呢?
    这里的想法与 StackOverflow 的思路相同。文档中的术语具有相关性,但如果文档带有术语标记,或者在标题中,则应该提升它。
    Java documentation 建议文档结构如下:
  • 标题
  • 问题
  • 接受的答案(如果没有接受的答案,则为高票答案)
  • 所有答案合并

  • 然后使用 boost 但不是基于原始投票值。我相信我已经涵盖了威尔逊分数区间。
    问题是,提升是否应该应用于整个文档?我倾向于否定这个,因为这意味着每次用户对模型进行投票时我都必须重新索引文档。
    搜索标记为 的项目
    我最初认为在查询标签时(通过专门单击一个或使用 URL 结构查找标签内容),这是针对标签的标签索引的简单 TermQuery,然后在关联索引中(如果需要)然后返回对于问题,Lucene.NET 处理得非常快。
    但是,鉴于上面关于在 SQL Server 中执行此操作是多么容易的说明,我在搜索标记项时选择了该路线。
    一般搜索
    所以现在,最突出的问题是在对内容进行一般短语或术语搜索时,您如何以及如何整合其他信息(例如投票)以便以正确的顺序确定结果?例如,在 Lucene 上执行此搜索时,这些是前五个结果的计数(使用相关性选项卡时):
        q votes answers accepted answer votes asp.net highlights mvc highlights
    ------- ------- --------------------- ------------------ --------------
    21 26 51 2 2
    58 23 70 2 5
    29 24 40 3 4
    37 15 25 1 2
    59 23 47 2 2
    请注意,突出显示仅在结果页面的标题和摘要中,并且只是关于文档、标题、标签、回复中真正术语频率的次要指标(但它们被应用,这是另一个好问题)。
    所有这些是如何结合在一起的?
    在这一点上,我知道 Lucene.NET 会返回一个标准化的相关性分数,投票数据会给我一个威尔逊分数区间,我可以用它来确定置信度分数。
    我应该如何看待结合这两个分数来指示基于相关性和置信度的结果集的排序顺序?
    对我来说,这两者之间应该存在某种关系是显而易见的,但这种关系应该是什么,我在这一点上回避了。我知道随着时间的推移我必须改进它,但我真的迷失在这部分。
    我最初的想法是,如果相关性得分介于 0 和 1 之间并且置信度得分介于 0 和 1 之间,那么我可以执行以下操作:
    1 / ((e ^ cs) * (e ^ rs))
    通过这种方式,一个归一化的值越接近 0,结果越相关和可信,并且可以对其进行排序。
    主要问题是,如果在标签和/或标题字段上执行提升,那么相关性得分超出 0 到 1 的范围(然后上限变得无界,我不知道如何处理) )。
    此外,我相信我将不得不调整置信度分数以解释完全为负的投票数。由于完全否定的投票结果导致威尔逊分数区间的下限为 0,因此具有 -500 票的事物与具有 -1 票或 0 票的事物具有相同的置信度分数。
    幸运的是,随着反对票数的增加,上限从 1 减少到 0。我可以将置信度分数更改为 -1 到 1 的范围,如下所示:
    confidence score = votetally < 0 ? 
    -(1 - wilson score interval upper bound) :
    wilson score interval lower bound
    这样做的问题是,将 0 代入等式将使所有零票数的项目排名低于负票数的项目。
    为此,我在考虑是否将置信度分数用于上述倒数方程(我显然担心溢出),那么它需要重新设计以始终为正值。实现这一目标的一种方法是:
    confidence score = 0.5 + 
    (votetally < 0 ?
    -(1 - wilson score interval upper bound) :
    wilson score interval lower bound) / 2
    我的其他问题是如何实际执行给定 Lucene.NET 和 SQL Server 的计算。我犹豫是否将置信度分数放在 Lucene 索引中,因为它需要使用字段缓存,这会对内存消耗产生巨大影响(如前所述)。
    我的一个想法是从 Lucene.NET 获取相关性分数,然后使用 Shashikant Kore 将分数传输到 SQL Server(以及要选择的项目的 id),此时我会充满信心地执行计算得分,然后返回正确排序的数据。
    如前所述,我对此还有很多其他问题,这些答案已经开始形成框架,并将随着问题和答案的发展而继续扩展。

    最佳答案

    单独使用 lucene 确实无法找到您正在寻找的答案。您需要排名和分组算法来过滤和理解数据及其关联方式。 Lucene 可以帮助您获取规范化数据,但之后您需要正确的算法。

    我建议您查看以下一本书或所有书,它们将帮助您进行数学运算并让您指明正确的方向:

    Algorithms of the Intelligent Web

    Collective Intelligence in Action

    Programming Collective Intelligence

    关于sql-server-2008 - 如何使用 Lucene.NET 帮助在 Stack Overflow 等网站上实现搜索?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2297794/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com