Запрет "слишком много статей" в запросе lucene

В моих тестах я неожиданно столкнулся с исключением "Слишком много статей" при попытке получить попадания из логического запроса, состоящего из запроса запроса и символа подстановки.

Я искал по сети и на найденных ресурсах они предлагают увеличить BooleanQuery.SetMaxClauseCount().
Это звучит подозрительно для меня.. К чему мне это? Как я могу рассчитывать, что этого нового магического числа будет достаточно для моего запроса? Как далеко я могу увеличить это число до того, как все начнется ад?

В общем, я чувствую, что это не решение проблемы. Там должна быть более глубокая проблема..

Запрос был +{+companyName:mercedes +paintCode:a*}, а индекс содержит ~2,5 млн документов.

2 ответа

Решение

paintCode:a* часть запроса является префиксным запросом для любого paintCode, начинающегося с "a". Это то, к чему вы стремитесь?

Lucene расширяет префиксные запросы в логический запрос, содержащий все возможные термины, соответствующие префиксу. В вашем случае, видимо, существует более 1024 возможных paintCodeы, которые начинаются с "а".

Если вам кажется, что префиксные запросы бесполезны, вы не далеки от истины.

Я бы посоветовал вам изменить схему индексации, чтобы избежать использования префиксного запроса. Я не уверен, что вы пытаетесь выполнить в своем примере, но если вы хотите искать коды рисования по первой букве, создайте поле paintCodeFirstLetter и выполните поиск по этому полю.

ADDED

Если вы в отчаянии и готовы принять частичные результаты, вы можете создать свою собственную версию Lucene из исходного кода. Вам нужно внести изменения в файлы PrefixQuery.java а также MultiTermQuery.javaоба под org/apache/lucene/search, в rewrite метод обоих классов, изменить строку

query.add(tq, BooleanClause.Occur.SHOULD);          // add to query

в

try {
    query.add(tq, BooleanClause.Occur.SHOULD);          // add to query
} catch (TooManyClauses e) {
    break;
}

Я сделал это для моего собственного проекта, и это работает.

Если вам действительно не нравится идея изменения Lucene, вы можете написать свой собственный вариант Prefix Query и свой собственный QueryParser, но я не думаю, что это намного лучше.

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

Здесь есть предложение, которое кажется мне довольно элегантным: http://grokbase.com/t/lucene.apache.org/java-user/2007/11/substring-indexing-to-avoid-toomanyclauses-exception/12f7s7kzp2emktbn66tdmfpcxfya

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

Пример:

Представьте себе paintCode как это:

"a4c2d3"

При индексации этого значения в документе создаются следующие значения полей:

[paintCode]: "a4c2d3"

[paintCode1n]: "a"

[paintCode2n]: "a4"

[paintCode3n]: "a4c"

К тому времени, когда вы сделаете запрос, количество символов в вашем термине определит, в каком поле искать. Это означает, что вы будете выполнять запрос префикса только для терминов, содержащих более 3 символов, что значительно уменьшает количество внутренних результатов, предотвращая печально известное исключение TooManyBooleanClausesException. По-видимому, это также ускоряет процесс поиска.

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

Некоторые проблемы могут возникнуть, если у вас есть несколько токенов для каждого поля. Вы можете найти более подробную информацию в статье

Другие вопросы по тегам