2015-01-16 1 views
4

Я пытаюсь выяснить, как фильтровать очень большой набор документов на основе соответствия ключевых слов.Альтернативы поиску программного обеспечения/серверов для получения идентификаторов для всех соответствующих документов

У меня есть 20 + миллионов записей с идентификатором и (несколькими) текстовыми полями в моей базе данных SQL, и я хочу получить все идентификаторы, для которых текст соответствует набору ключевых слов. Сюда относятся более сложные выражения, такие как:

(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, но мне интересно, есть ли какая-либо другая технология, специально оптимизированная для этой проблемы ?

+1

Не может помочь реальный вопрос, но пока Sphinx не имеет явной поддержки «курсора», его довольно легко настроить с помощью доступных опций. Я смог получить порядка миллионов идентификаторов за 2-3 секунды для сложного запроса. – barryhunter

+0

Не могли бы вы объяснить немного больше, как вы получаете это представление? Те тесты, которые я сделал с Sphinx, просто требуя с повышенным смещением LIMIT, на самом деле не являются удовлетворительными, потому что похоже, что он выполняет новый поиск каждый раз, хотя я остался под значением MAX_MATCHES. Разве он не должен хранить результаты в памяти? Также, если я увеличиваю MAX_MATCHES до значения, которое позволяет получить все соответствующие документы, запросы будут довольно медленными с точностью до 10 с (по очень базовому и неоптимизированному индексу). – dennis

+1

Ну, идея НЕ делать с LIMIT. Как вы говорите, это ужасно неэффективно. Необходимо внедрить реальную систему курсора, используя фильтр, а не смещение/ограничение. Пример здесь: http://sphinxsearch.com/forum/view.html?id=7215 - но может выжать больше производительности, используя SphinxQL, и осторожное использование опции CUTOFF. (также может использовать распределенный индекс, который может использовать современные многоядерные процессоры) – barryhunter

ответ

3

Из того, что я понимаю, сила Lucene/Solr, Sphinx и ElasticSearch заключается в том, чтобы вернуть документы TOP быстрее, но они на самом деле не предназначены для возврата ВСЕХ документов.

На самом деле это было правдой, но в последние годы стало намного лучше. Я буду откладывать другие, когда речь заходит о других вариантах программного обеспечения, но Lucene в начале серии 4.x сделала некоторые улучшения, чтобы сделать эффективную глубокую разбивку на страницы с помощью курсора.

Elasticsearch обладает особенно приятным API для этого: Scrolling Search. Чтобы использовать его, вы предоставляете свой поисковый запрос с параметром scroll. Затем он возвращает курсор scroll_id, который вы используете для последующих запросов для каждой страницы.

Если вы не хотите сортировать и хотите, чтобы все документы были возвращены, вы также можете указать тип поиска scan. Это вернет все документы в наиболее эффективном порядке, без какой-либо конкретной сортировки.

Я прояснил некоторые подробности здесь, вам нужно будет ознакомиться с документацией Scrolling Search для более подробного описания.

Solr также поддерживает глубокую разбивку на страницы с Solr 4.7 в SOLR-5463. Он добавляет поддержку параметра cursorMark, который будет использоваться вместе с вашими поисковыми запросами. Затем Solr возвращает nextCursorMark, указывая на каждую последующую страницу.

См. Раздел «Использование курсоров» в документации Solr Pagination of Results.

Похоже, что OP уже знаком с этими вариантами, но я подумал, что это стоит того, чтобы с дружелюбием с подобным вопросом.

Также интересно: my take on the mechanics and efficiency of an Elasticsearch scrolling search.

+0

Хмм, прокрутка поиска, похоже, в значительной степени соответствует требованиям «специально для этой проблемы» :) – barryhunter

+0

Мои мысли точно! –

+0

Проблема, которую я вижу с разбивкой по страницам, будет заключаться в том, что индекс должен быть запрошен для каждой новой «страницы». По крайней мере, так я это понимаю. Это кажется довольно неэффективным, учитывая, что каждый соответствующий документ уже был посещен один раз, особенно с запросами, которые занимают больше секунды. – dennis

0

В случае, если это полезно для тех, кто имеет дело с одной и той же проблемой, вот решение, с которым я иду.

Я использую Lucene с пользовательским сборщиком, который хранит все соответствующие идентификаторы, без обработки:

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) { } 
} 

Таким образом, можно собрать все ~ идентификаторы 30mio для каждого подходящего документа в течение примерно 5,5 секунд для запрос как term1* OR term2* OR term3* OR term4*.

К сожалению, скорость поиска, вероятно, неизбежна, зависит от количества обращений, даже без учета, сортировки или аналогичной обработки хитов.

Смежные вопросы