Запрет "слишком много статей" в запросе lucene - PullRequest
10 голосов
/ 05 марта 2009

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

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

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

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

Ответы [ 2 ]

3 голосов
/ 05 марта 2009

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

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

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

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

ДОБАВЛЕНО

Если вы в отчаянии и готовы принять частичные результаты, вы можете создать свою собственную версию 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, вы можете написать свой собственный вариант PrefixQuery и собственный QueryParser, но я не думаю, что он намного лучше.

0 голосов
/ 14 декабря 2011

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

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

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

Пример:

Представьте себе код краски, подобный этому:

"a4c2d3"

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

[paintCode]: "a4c2d3"

[paintCode1n]: "a"

[paintCode2n]: "a4"

[paintCode3n]: "a4c"

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...