【问题标题】:Lucene: how to stop searching in the current document after the first matchLucene:如何在第一次匹配后停止在当前文档中搜索
【发布时间】:2012-02-04 01:10:10
【问题描述】:

标题可能有点含糊,但请耐心等待(我能找到的唯一类似问题是Solr: Search in multiple fields BUT STOP if documents match was found,但没有提供任何解决方案)。我的 lucene 文档具有以下结构:

FieldA (Store.YES, Index.ANALYZED), primary identification of an entity
FieldB (Store.YES, Index.ANALYZED), secondary identification(s) of an entity

FieldA 可以包含例如car 之类的字符串,其中FieldB 可以包含automobilevehicle 等字符串。文档中可以有多个FieldB 字段。索引分析器是StandardAnalyzer,搜索分析器是KeywordAnalyzer(这似乎产生了最好的结果,不确定它是否是最好的方法)。 FieldA 中的标识符比FieldB 中的标识符更重要。

假设索引包含 3 个文档(带有 FieldA | FieldB 字段):

"car"       | "vehicle" "automobile"
"car parts" | "parts, car"
"car shop"  | "shop, car"

到目前为止,一切都很好。现在问题出在哪里:

在查询"car"时,我想看到如下结果(分数是补的):

car, score 1.0
car parts, score 0.9
car shop, score 0.9

FieldA 值为 "car" 的文档应首先显示,因为 FieldA 被认为更重要,并且查询与该值最匹配。实际上,会发生以下情况:

car parts, score 0.625
car shop, score 0.625
car, score 0.5073969

searcher.explain() 输出以下内容:(留下“汽车商店”的解释,因为它与“汽车零件”相同)

Explain: 0.625 = (MATCH) max of:
  0.31712303 = (MATCH) weight(fielda:car in 0), product of:
    0.71231794 = queryWeight(fielda:car), product of:
      0.71231794 = idf(docFreq=3, maxDocs=3)
      1.0 = queryNorm
    0.4451987 = (MATCH) fieldWeight(fielda:car in 0), product of:
      1.0 = tf(termFreq(fielda:car)=1)
      0.71231794 = idf(docFreq=3, maxDocs=3)
      0.625 = fieldNorm(field=fielda, doc=0)
  0.625 = (MATCH) fieldWeight(fieldb:car in 0), product of:
    1.0 = tf(termFreq(fieldb:car)=1)
    1.0 = idf(docFreq=2, maxDocs=3)
    0.625 = fieldNorm(field=fieldb, doc=0)
Explain: 0.5073969 = (MATCH) max of:
  0.5073969 = (MATCH) weight(fielda:car in 0), product of:
    0.71231794 = queryWeight(fielda:car), product of:
      0.71231794 = idf(docFreq=3, maxDocs=3)
      1.0 = queryNorm
    0.71231794 = (MATCH) fieldWeight(fielda:car in 0), product of:
      1.0 = tf(termFreq(fielda:car)=1)
      0.71231794 = idf(docFreq=3, maxDocs=3)
      1.0 = fieldNorm(field=fielda, doc=0)

TL;DR:对于这两个字段,提升 FieldA 将无济于事,因为所有 3 个文档都会得到提升。如何让lucene将最接近的匹配(本例中的“汽车”)排名最高?即遇到FieldA中的(更重要的)匹配后如何停止在当前文档中搜索?

【问题讨论】:

    标签: java lucene


    【解决方案1】:

    使用 NOT 语法。

    a:car^2 (+b:car -a:car)

    这样在 b 中匹配的将被忽略,除非它们无法匹配 a。

    【讨论】:

    • 这解决了一个术语出现在两个字段上的问题,但一如既往地存在潜在问题。
    【解决方案2】:

    问题在于,在 fieldb 中,汽车仅在三个术语中的两个中找到,而在 fielda 中,汽车在所有三个术语中都存在。因此,在 fieldb 中与 car 的匹配得分更高,因为它具有更高的 idf(1.0 与 0.7123174 相比)

    匹配的值本质上是:

    idf * idf * fieldnorm * tf

    fieldnorm 在哪里

    lengthnorm * fieldboost
    

    所以你可以看到 idf 非常重要。

    实际上,如果您确实提升了字段 a 将起作用,因为与字段 b 上的匹配相比,字段 a 上的匹配会得到提升,并且在您的示例中,字段 b 上的匹配排名更高。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-27
      • 1970-01-01
      • 2023-01-30
      • 2015-07-17
      • 1970-01-01
      • 1970-01-01
      • 2023-01-13
      • 2016-09-26
      相关资源
      最近更新 更多