Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Lucene地理距离排序性能_Java_Sorting_Lucene_Geospatial - Fatal编程技术网

Java Lucene地理距离排序性能

Java Lucene地理距离排序性能,java,sorting,lucene,geospatial,Java,Sorting,Lucene,Geospatial,我的任务是不仅根据索引文档的字符串字段的相关性,而且还根据从给定地理点到与每个被索引文档相关联的点的距离,对搜索结果进行排序。应该提到的是,只有前十名左右的匹配文档才应包含在结果集中。此外,按精确的距离排序也不重要,重要的是距给定点的“距离级别” 从技术上讲,我已经成功地完成了这项任务。任务的地理部分作为CustomScoreQuery派生类实现: private static class DistanceQuery extends CustomScoreQuery { public Di

我的任务是不仅根据索引文档的字符串字段的相关性,而且还根据从给定地理点到与每个被索引文档相关联的点的距离,对搜索结果进行排序。应该提到的是,只有前十名左右的匹配文档才应包含在结果集中。此外,按精确的距离排序也不重要,重要的是距给定点的“距离级别”

从技术上讲,我已经成功地完成了这项任务。任务的地理部分作为
CustomScoreQuery
派生类实现:

private static class DistanceQuery extends CustomScoreQuery {

  public DistanceQuery(final Query _subQuery, final SpatialStrategy _strategy, final Point _bp) {
    super(_subQuery, new FunctionQuery(_strategy.makeDistanceValueSource(_bp)));
  }

  @Override
  protected CustomScoreProvider getCustomScoreProvider(AtomicReaderContext _context) throws IOException {
    return new CustomScoreProvider(_context) {
      @Override
      public float customScore(int _doc, float _subQueryScore, float _valSrcScore) throws IOException {
        // the spatial strategies makeDistanceValueSource creates a ValueSource which score varies from almost 0 for nearby points to 2.7-2.8 for distant points
        // so I voluntarily chosen 2 as the normalization factor and increase subQueryScore for that factor at max;
        logger.debug("customScore for document {}: [subQuery={}, valScore={}", this.context.reader().document(_doc).getField(IndexedField.id.name()).numericValue().toString(), _subQueryScore, _valSrcScore);
        return (_valSrcScore > 2 || _valSrcScore < 0) ? _subQueryScore : _subQueryScore + (2 - _valSrcScore);
      }
    };
  }
}
私有静态类DistanceQuery扩展了CustomScoreQuery{
公共距离查询(最终查询子查询、最终空间策略、最终点bp){
超级(_子查询,新函数查询(_strategy.makeDistanceValueSource(_bp));
}
@凌驾
受保护的CustomScoreProvider getCustomScoreProvider(AtomicReaderContext\u上下文)引发IOException{
返回新的CustomScoreProvider(\u上下文){
@凌驾
公共浮点customScore(int\u doc,float\u subQueryScore,float\u valsrccore)抛出IOException{
//空间策略makeDistanceValueSource创建了一个ValueSource,其分数从附近点的几乎0到远处点的2.7-2.8不等
//所以我自愿选择2作为标准化因子,并将该因子的子查询核增加到最大值;
logger.debug(“文档{}:[subQuery={},valScore={},”,this.context.reader().document(_doc).getField(IndexedField.id.name()).numericValue().toString(),_subQueryScore,_valsrccore());
返回(_valsrccore>2| | | _valsrccore<0)?_子查询分数:_子查询分数+(2-_valsrccore);
}
};
}
}
并使用此地理空间“增强功能”包装给定的“文本”查询

一般来说,所选择的策略给了我相当合理的结果。正如人们可能看到的,最终的分数只是略高于初始查询分数(最多2分)。而且,对于十几个或更多的典型结果分数,这种地理空间的添加就像是对类似文档进行“后期排序”的一种方式

索引中有数百或数千个测试文档,包装查询的性能也足够好。每次搜索大约10-50毫秒,比未包装查询慢2-5倍

但是当我从测试切换到现实世界的数据库时,索引中的文档数量从1000个增加到大约1000万个,并且还会增加更多(估计在不久的将来会增加1亿个),然后情况发生了巨大的变化。实际上,我无法再获得任何搜索结果,因为JVM的内存和处理器都用完了。目前,它无法在JVM中使用-Xmx6g或更多来完成搜索。 当然,我可以为这项任务购买更好的硬件,但问题可能会通过选择更合适的排序策略来解决

一个解决方案是完全避免Lucene提供的地理排序,如果项目相关性得分相似,则手动排序结果集中的前N个项目。如果没有其他帮助,我将选择这种方式


但我的问题是是否存在更充分的解决方案。也许我可以通过某种方式将结果项按等价类(分数相同或相似)进行划分并且只对前几个类应用地理空间排序?请建议。

看看elasticsearch是如何在函数_scorequery中实现这一点的。你可能可以重用他们所做的一些事情。如果我没记错的话,他们也可以选择使用更快但更不准确的距离计算算法。你可能想做一些类似的情况。

我正在使用另一个CustomScoreProvider进行距离查询:

public class DistanceQueryScoreProvider extends CustomScoreProvider {

    private double x;
    private double y;

    public DistanceQueryScoreProvider(LeafReaderContext context, double x, double y) {
        super(context);
        this.x = x;
        this.y = y;
    }

    @Override
    public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
        Document d = context.reader().document(doc);
        double geomX = d.getField(Consts.GEOM_X_FIELD).numericValue().doubleValue();
        double geomY = d.getField(Consts.GEOM_Y_FIELD).numericValue().doubleValue();
        double deglen = 110.25;
        double deltaX = geomY - y;
        double deltaY = (geomX - x) * Math.cos(y);
        return -Double.valueOf(deglen * Math.sqrt(deltaX * deltaX + deltaY * deltaY)).floatValue();
    }
}
平面
距离函数的弹性搜索比上面的代码函数customScore慢。此函数是根据文章实现的


用户3159253,也许你有这个帖子的答案?

好的,谢谢!我将评估这个可能性,然后写一个回复,并批准你的答案,希望在一天左右。