gpt4 book ai didi

lucene - 在 Lucene 中将来自多个文档的命中合并为一个命中

转载 作者:行者123 更新时间:2023-12-04 07:04:01 26 4
gpt4 key购买 nike

我试图让特定的搜索工作,但事实证明这是有问题的。实际的源数据相当复杂,但可以通过以下示例进行总结:

I have articles that are indexed so that they can be searched. Each article also has multiple properties associated with it which are also indexed and searchable. When users search, they can get hits in either the main article or the associated properties. Regardless of where a hit is achieved, the article is returned as a search hit (ie. the properties are never a hit in their own right).



现在的复杂性:

Each property has security on it, which means that for any given user, they may or may not be able to see the property. If a user cannot see a property, they obviously do not get a search hit in it. This security check is proprietary and cannot be done using the typical mechanism of storing a role in the index alongside the other fields in the document.



我目前有一个索引,其中包含单独索引的文章和属性(即,文章被索引为文档,并且每个属性都有自己的文档)。发生搜索时,应将文章 A 中的命中或文章 A 的任何属性中的命中归类为单独针对文章 A 的命中,并将分数相加。

为了最初实现这一点,Lucene v1.3 被修改为允许通过将 BooleanQuery 更改为具有自定义 Scorer 来实现这一点,该 Scorer 可以应用安全检查的逻辑,并将不同文档中的两个匹配项的组合归类为单个匹配项文档。我正在尝试将此版本升级到最新版本(v2.3.2 - 我使用的是 Lucene.Net),但理想情况下无需以任何方式修改 Lucene。

如果我进行 AND 搜索,则会出现另一个问题。如果文章包含单词 foo 并且其属性之一包含单词 bar,则搜索“foo AND bar”将返回该文章作为命中。我当前的代码在自定义记分器中处理这个问题。

任何想法如何/是否可以做到这一点?

我正在考虑使用自定义 HitCollector 并将其传递到搜索中,但是在执行 bool 搜索“foo AND bar”时,执行永远不会到达我的 HitCollector,因为 ConjunctionScorer 过滤掉了之前来自子查询的所有结果到达那里。

编辑:

用户能否看到一个属性,不是基于属性本身,而是基于属性的值(value)。因此,我无法预先将额外的安全条件放入查询中,因为我不知道要过滤的值。

举个例子:
+---------+------------+------------+
| Article | Property 1 | Property 2 |
+---------+------------+------------+
| A | X | J |
| B | Y | K |
| C | Z | L |
+---------+------------+------------+

如果用户可以看到所有内容,则搜索“B 和 Y”将返回文章 B 的单个搜索结果。

如果其他用户无法看到属性值包含 Y 的属性,则搜索“B 和 Y”将不会返回任何匹配项。

我无法知道用户可以和不能预先看到哪些值。他们唯一的判断方法是执行安全检查(目前在从文档中的字段过滤命中时完成),显然我无法对每个用户的每个可能的数据值执行此操作。

最佳答案

现在已经实现了这个(经过大量的挠头和逐步完成 Lucene 搜索),我想我会回帖我是如何实现它的。

因为我对所有结果都感兴趣(即一次不是一个页面),所以我可以避免使用 Hits对象(无论如何在更高版本的 Lucene 中已被弃用)。这意味着我可以使用 Search(Weight, Filter, HitCollector) 来做我自己的热门收藏。 IndexSearcher的方法,迭代所有可能的结果并适当组合文档命中。为此,我必须使用 Lucene 的查询机制,但仅当存在 AND 和 NOT 子句时。这是通过以下方式实现的:

  • 创建自定义 QueryParser和覆盖 GetBooleanQuery(ArrayList, bool)返回我自己的实现。
  • 创建自定义 BooleanQuery (从自定义 QueryParser 返回)和覆盖 CreateWeight(Searcher)返回我自己的实现。
  • 创建自定义 Weight (从自定义 BooleanQuery 返回)和覆盖 Scorer(IndexReader)返回我自己的实现。
  • 创建自定义 BooleanScorer2 (从自定义 Weight 返回)并覆盖 Score(HitCollector)方法。这就是处理自定义逻辑的内容。

  • 这可能看起来像很多类,但它们中的大多数都是从 Lucene 类派生的,只是覆盖了一个方法。
    Score(HitCollector)的执行自定义中的方法 BooleanScorer2类现在负责执行自定义逻辑。如果没有需要的子评分者,评分可以传递给基础 Score方法并正常运行。如果需要子评分器,则表示查询中存在 NOT 或 AND 子句。在这种情况下,问题中提到的特殊组合逻辑就起作用了。我有一个类(class)叫 ConjunctionScorer这样做(这与 Lucene 中的 ConjunctionScorer 无关)。
    ConjunctionScorer获取评分者列表并对其进行迭代。对于每一个,我提取命中及其分数(使用 Doc()Score() 方法)并创建我自己的搜索命中集合,其中仅包含当前用户在执行相关安全检查后可以看到的那些命中。如果另一个得分手已经找到了命中,我将它们组合在一起(使用他们的得分平均值作为他们的新得分)。如果命中来自被禁止的得分手,如果已经找到命中,我将删除该命中。

    在所有这一切结束时,我将点击数设置为 HitCollector传入 BooleanScorer2.Score(HitCollector)方法。这是一个定制 HitCollector我传入了 IndexSearcher.Search(Query, HitCollector)最初执行搜索的方法。当此方法返回时,我的自定义 HitCollector现在包含我想要的组合在一起的搜索结果。

    希望这些信息对面临同样问题的其他人有用。这听起来很努力,但实际上非常简单。大多数工作是在 ConjunctionScorer 中将命中组合在一起完成的。 .请注意,这是针对 Lucene v2.3.2 的,在以后的版本中可能会有所不同。

    关于lucene - 在 Lucene 中将来自多个文档的命中合并为一个命中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1393551/

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