Java 在Lucene中获取子查询的子分数

Java 在Lucene中获取子查询的子分数,java,scala,lucene,Java,Scala,Lucene,我构造了一个查询,它本质上是其他查询的加权和: val query = new BooleanQuery for ((subQuery, weight) <- ...) { subQuery.setBoost(weight) query.add(subQuery, BooleanClause.Occur.MUST) } val query=新布尔查询 对于((子查询,权重)有一个记分器导航API:基本思想是编写一个收集器,并在其setScorer方法中,通常保存对该记分器的引用以

我构造了一个查询,它本质上是其他查询的加权和:

val query = new BooleanQuery
for ((subQuery, weight) <- ...) {
  subQuery.setBoost(weight)
  query.add(subQuery, BooleanClause.Occur.MUST)
}
val query=新布尔查询

对于((子查询,权重)有一个记分器导航API:基本思想是编写一个收集器,并在其setScorer方法中,通常保存对该记分器的引用以供以后记分()每次点击,现在可以遍历该记分器的子记分器的树,依此类推

请注意,记分器具有指向创建它们的权重的指针,以及返回查询的权重

使用所有这些,您可以隐藏对您在setScorer方法中关心的子Corer的引用,例如所有从TermQueries创建的子Corer。然后,在对命中率进行评分时,您可以在收集器中对这些节点的freq()和score()等进行调查

在3.x系列中,这是一个仅限于布尔关系的访问者API;在4.x系列中(目前只有alpha版本),您只需获取每个子核心器的child+关系,因此它可以处理任意查询(包括您编写的自定义查询或其他查询)

注意事项:

  • 您需要从收集器中的AcceptsDocSoutoOrder返回false,因为收集器需要一次处理一个文档才能工作。
  • 您可能需要3.6系列()的错误修复分支或4.x()的快照。这是因为自析取(或查询)之后,此功能通常不起作用在上周某些问题得到解决之前,始终将他们的子核心设置为“提前一个文档”,而这些问题并没有及时解决3.6.1中的问题。有关更多详细信息,请参阅。
  • 除了一些简单的测试总结了所有叶节点的术语频率外,没有什么好的例子(见下文)
测试:

  • 4.x系列:
  • 3.x系列:
谢谢您提供的所有详细信息。我从收集器路径开始,但我不知道如何“遍历该记分器的子记分器的树”。您能否给出一些示例代码来说明如何做到这一点?看看这些测试。在4.x中,您在记分器上调用getChildren()并自行导航。在3.x中,您必须使用访问者
for (scoreDoc <- searcher.search(query, nHits).scoreDocs) {
  val score = scoreDoc.score
  val subScores = subQueries.map { subQuery =>
    val weight = searcher.createNormalizedWeight(subQuery)
    val scorer = weight.scorer(reader, true, true)
    scorer.advance(scoreDoc.doc)
    scorer.score
  }
}
val query = new BooleanQuery
for ((subQuery, weight) <- ...) {
  val weightedQuery = new BoostedQuery(subQuery, new ConstValueSource(weight))
  query.add(weightedQuery, BooleanClause.Occur.MUST)
}
val collector = new DocScoresCollector(nHits)
searcher.search(query, collector)
for (docScores <- collector.getDocSubScores) {
  ...
}
class DocScoresCollector(maxSize: Int) extends Collector {
  var scorer: Scorer = null
  var subScorers: Seq[Scorer] = null
  val priorityQueue = new DocScoresPriorityQueue(maxSize)

  override def setScorer(scorer: Scorer): Unit = {
    this.scorer = scorer
    // a little reflection hackery is required here because of a bug in
    // BoostedQuery's scorer's getChildren method
    // https://issues.apache.org/jira/browse/LUCENE-4261
    this.subScorers = scorer.getChildren.asScala.map(childScorer =>
      childScorer.child ...some hackery... ).toList
  }

  override def acceptsDocsOutOfOrder: Boolean = false

  override def collect(doc: Int): Unit = {
    this.scorer.advance(doc)
    val score = this.scorer.score
    val subScores = this.subScorers.map(_.score)
    priorityQueue.insertWithOverflow(DocScores(doc, score, subScores))
  }

  override def setNextReader(context: AtomicReaderContext): Unit = {}

  def getDocSubScores: Seq[DocScores] = {
    val buffer = Buffer.empty[DocScores]
    while (this.priorityQueue.size > 0) {
      buffer += this.priorityQueue.pop
    }
    buffer
  }
}

case class DocScores(doc: Int, score: Float, subScores: Seq[Float])

class DocScoresPriorityQueue(maxSize: Int) extends PriorityQueue[DocScores](maxSize) {
  def lessThan(a: DocScores, b: DocScores) = a.score < b.score
}