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

时间:2015-01-16 14:46:58

标签: solr elasticsearch lucene sphinx

我试图弄清楚如何根据关键字匹配过滤一大堆文档。

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

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

不需要以任何方式对结果进行评分,排序或排名。

据我了解Lucene / Solr的强大功能,Sphinx和ElasticSearch将以极快的速度回馈TOP文档,但它们并非真正打算回赠所有文档。

我知道可以使用Lucene中的自定义收集器(请参阅What's the most efficient way to retrieve all matching documents from a query in Lucene, unsorted?)以及可能使用Solr / Elasticsearch中的Cursors / Scrolling来执行此操作,但我想知道是否有任何其他技术经过专门优化对于这个问题?

2 个答案:

答案 0 :(得分:3)

  

据我了解Lucene / Solr的强大功能,Sphinx和ElasticSearch将以极快的速度回馈TOP文档,但它们并非真正打算回赠所有文档。

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

Elasticsearch有一个特别好的API:Scrolling Search。要使用它,请使用scroll参数提供搜索查询。然后它返回一个scroll_id光标,用于为每个页面发出后续请求。

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

我在这里隐瞒了一些细节,您需要查看Scrolling Search文档以获得更详尽的说明。

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

请参阅Solr的Pagination of Results文档中的“使用游标”部分。

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

同样有趣:my take on the mechanics and efficiency of an Elasticsearch scrolling search

答案 1 :(得分:0)

如果对处理相同问题的任何人都有帮助,这就是我要解决的问题。

我正在使用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。

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