【问题标题】:How tightly can Marklogic search scores be controlled?Marklogic 搜索分数可以控制多严?
【发布时间】:2012-11-08 14:15:19
【问题描述】:

我们的数据库包含具有大量元数据的文档,包括这些文档之间的关系。虚构示例:

<document>
  <metadata>
    <document-number>ID 12345 : 2012</document-number>
    <publication-year>2012</publication-year>
    <cross-reference>ID 67890 : 1995</cross-reference>
    <cross-reference>ID 67890 : 1998</cross-reference>
    <cross-reference>ID 67891 : 2000</cross-reference>
    <cross-reference>ID 12345 : 2004</cross-reference>
    <supersedes>ID 12345 : 2004</supersedes>
    ...
  </metadata>
</document>
<document>
  <metadata>
    <document-number>ID 12345 : 2004</document-number>
    <publication-year>2004</publication-year>
    <cross-reference>ID 67890 : 1995</cross-reference>
    <cross-reference>ID 67890 : 1998</cross-reference>
    <cross-reference>ID 67891 : 2000</cross-reference>
    <cross-reference>ID 12345 : 2012</cross-reference>
    <cross-reference>ID 12345 : 2001</cross-reference>
    <superseded-by>ID 12345 : 2012</superseded-by>
    <supersedes>ID 12345 : 2001</supersedes>
    ...
  </metadata>
</document>

我们正在使用基于 Marklogic 搜索 API 的单框搜索来允许用户搜索这些文档。搜索语法描述了各种约束和搜索选项,但大多数情况下(默认情况下)它们通过定义为包含大多数元数据元素的字段进行搜索,并(在某种程度上)仔细选择权重(这里真正重要的是document-number权重最高。)

问题是业务需要非常具体的结果排序,我想不出使用搜索 api 实现它的方法。

导致问题的要求是,如果用户搜索匹配文档编号(例如他们搜索“12345”),则具有该文档编号的所有文档都应位于结果集的顶部,按日期降序排列.将它们放在结果集的顶部很容易; document-number 的权重最高,因此按分数排序可以正常工作。问题是按日期进行二次排序不起作用,因为即使所有 document-number 匹配的分数都高于其他文档,但它们没有 same 分数,因此它们最终被排序搜索词在其余元数据中出现的频率;这根本没有真正的意义。

我认为我们真正需要的是一种仅通过与搜索词匹配的最高权重元素来获得搜索 api 得分结果的方法,而无需参考文档中的任何其他匹配项。我已经查看了评分算法,但看不到这样做的算法;我错过了什么或者这不可能吗?显然,我们订购的不一定是score;如果有其他方法可以获取文档中单个最佳匹配的分数并将其用于排序,那很好。

还有其他我没想到的解决方案吗?

我想过进行两次搜索(一次在 document-number 上,一次在整个元数据树上)然后合并结果,但这似乎会给分页和性能带来很多麻烦。哪一种首先违背了使用搜索 api 的目的。

我应该补充一点,在结果集中包含其他匹配项是正确的,因此我们不能只搜索document-number

【问题讨论】:

    标签: xquery marklogic


    【解决方案1】:

    我认为您已经达到了高级搜索 API 可以为您做的事情的极限。不过,我有一些技巧要建议。这些不会是 100% 健壮的,但它们可能对业务来说已经足够好了。然后你就可以继续申请了。对不起,如果我听起来愤世嫉俗或不屑一顾,但我不相信对搜索结果进行微观管理。

    最简单的方法:重新排序内存中的第一页。第一页可能比您向用户显示的页面大一点。因为它的大小仍然有限,所以您可以为这个相当复杂的规则制定规则而不会受到太大影响。这将解决您的“递减日期”问题。第 1 页的结果与第 2 页的结果不太匹配,但这可能已经足够了。

    在复杂性上迈出下一步,考虑使用文档质量来处理递减日期问题。 http://markmail.org 等使用此方法。在插入或更新每个文档时,使用从日期派生的数字设置文档质量。这可能是自 1970 年以来的几天、几周或几个月,或者使用其他一些固定日期。较新的结果往往会浮到顶部。如果任何其他提升往往会淹没基于日期的提升,那么您可能会接近您想要的。

    分析查询以提取潜在的提升词可能也有一些用处。如有必要,您可以在每个提升术语上开始递归运行xdmp:exists(cts:search(doc(), $query)),就好像它是一个独立的查询一样。找到true() 结果后立即退出:这意味着您将用高得离谱的权重提升该查询词,使其浮到顶部。

    一旦你知道什么是提升词,重写整个查询,将所有其他词的权重设置为低得多的值,甚至可能为 0。权重越低,那些非提升词对基于日期的干扰就越少质量和增加重量。如果没有提升项,您可能需要进行其他调整。顺便说一句,所有这些都比听起来便宜。除了xdmp:exists 调用之外,它只是内存中的表达式求值。

    再一次,不过,这些都只是轻推分数的技巧。他们不会让您绝对控制您正在寻找的排名。以我的经验,对分数进行微观管理的尝试注定要失败。我敢打赌,无论您的业务经理说什么,您的用户都会对原始 TF/IDF 更满意。

    【讨论】:

      【解决方案2】:

      按照您的建议,另一种方法是使用两次搜索。在文档编号(理想情况下是文档日期)上放置一个范围索引,从查询中提取任何潜在的文档编号值(search:parse,提取,然后search:resolve 是一个很好的策略),然后执行 cts:element- range-query 用于匹配那些文档编号值且日期降序的文档。如果没有足够的结果来填满您的 N 个结果页面,则从搜索 api 获取下一个 N-x 个结果。您可以跟踪在第一个结果集中返回的文档,并从第二个结果集中排除这些 URI。跟踪分页不会太糟糕。

      这可能不如第一个解决方案执行得那么好,但是对于大多数人来说,附加范围索引查询与更短的搜索 api 查询相结合的时间差异应该可以忽略不计。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-15
        • 2012-04-12
        • 2014-05-24
        • 1970-01-01
        相关资源
        最近更新 更多