搜索软件/服务器的替代方法,用于检索所有匹配文档的 ID



我正在尝试弄清楚如何根据关键字匹配过滤大量文档。

我的 SQL 数据库中有 20+00 万个带有 ID 和(几个)文本字段的条目,我想获取文本与一组关键字匹配的所有 ID。这包括更复杂的表达式,例如:

 (term1 NEAR term2 NEAR term3) AND NOT "A phrase" AND @fieldXYZ "wildcards%aswell*"

结果不需要以任何方式评分、排序或排名。

据我所知,Lucene/Solr、Sphinx 和 ElasticSearch 的强大功能是超快地回馈 TOP 文档,但它们并不是真的打算回馈所有文档。

我知道可以使用Lucene中的

自定义收集器来执行此操作(请参阅从Lucene中的查询中检索所有匹配文档的最有效方法是什么,未排序?)并且可能使用Solr/Elasticsearch中的光标/滚动,但我想知道是否有任何其他技术专门针对此问题进行了优化?

据我所知,Lucene/Solr、Sphinx 和 ElasticSearch 的强大功能是超快地回馈 TOP 文档,但它们并不是真的打算回馈所有文档。

实际上,这曾经是真的,但近年来已经好多了。当涉及到其他软件选项时,我会尊重其他人,但Lucene确实在4.x系列的早期得到了一些改进,可以用光标进行高效的深度分页。

Elasticsearch有一个特别好的API:滚动搜索。若要使用它,请提供带有 scroll 参数的搜索查询。然后,它返回一个scroll_id游标,您可以使用该游标对每个页面发出后续请求。

如果您不关心排序,只想返回所有文档,那么您还可以指定搜索类型scan。这将以最有效的顺序返回所有文档,不应用特定的排序。

我已经在这里掩盖了一些细节,您需要查看滚动搜索文档以获取更全面的描述。

从SOLR-5463中的Solr 4.7开始,Solr还支持深度分页。它增加了对与搜索请求一起使用的cursorMark参数的支持。然后,Solr 返回指向每个后续页面的nextCursorMark

请参阅 Solr 的结果分页文档中的"使用游标"部分。

听起来 OP 已经熟悉这些选项,但我认为为了其他有类似问题的人而充实一下是值得的。

同样有趣的是:我对 Elasticsearch 滚动搜索的机制和效率的看法。

如果它对处理相同问题的任何人有帮助,这是我要采用的解决方案。

我正在使用带有自定义收集器的Lucene,该收集器存储所有匹配的ID,而无需任何处理:

class IDCollector : Collector
{
    // Offset for multiple reader
    private int docBase;
    // Stores IDs for all hits
    public List<int> HitList { get; set; }
    public IDCollector() 
    { 
         this.HitList = new List<int>(INITIAL_CAPACITY); 
    }
    public override void Collect(int doc) 
    { 
        HitList.Add(doc + docBase); 
    }
    // Order of docs does not matter
    public override bool AcceptsDocsOutOfOrder { get { return true; } }
    // Default implementation, docBase is the offset from reader
    public override void SetNextReader(IndexReader reader, int docBase) 
    { 
        this.docBase = docBase; 
    }
    // Scoring is not necessary
    public override void SetScorer(Scorer scorer) { }
}
这样,对于

term1* OR term2* OR term3* OR term4*这样的查询,可以在大约 5.5 秒内为每个匹配的文档收集所有 ~30mio ID。

不幸的是,但可能是不可避免的,即使没有任何评分、排序或类似的点击处理,搜索速度也非常依赖于点击次数。

最新更新