С Lucene: почему я получаю сообщение об ошибке "Слишком много предложений", если выполняю поиск по префиксу?

Некоторое время у меня было приложение, выполняющее поиск по префиксу. Недавно размер индекса был увеличен, и оказалось, что некоторые префиксы слишком многочисленны, чтобы lucene могла их обрабатывать. Это продолжало выдавать мне ошибку Too Many Clauses , что очень расстраивало, поскольку я продолжал смотреть в свои JAR и подтверждать, что ни один из включенных кодов на самом деле не использует логический запрос.

Почему он не генерирует что-то вроде исключения Too Many Hits? И почему увеличение целого числа static max clauses логического запроса фактически устраняет эту ошибку, если я определенно использую только префиксный запрос? Есть ли что-то фундаментальное в том, как выполняются запросы, чего я не понимаю; они тайно становятся логическими запросами?

Ответов (3)

Решение

Я уже сталкивался с этим раньше. Это связано с тем, что lucene под прикрытием превращает многие (все?) Вещи в логические запросы, когда вы вызываете Query.rewrite ()

Источник: http://web.archive.org/web/20110915061619/http://lucene.apache.org:80/java/2_2_0/api/org/apache/lucene/search/Query.html

public Query rewrite(IndexReader reader)
              throws IOException

    Expert: called to re-write queries into primitive queries.
            For example, a PrefixQuery will be rewritten into a
            BooleanQuery that consists of TermQuerys.

    Throws:
        IOException

При выполнении префиксного запроса Lucene ищет в своем «словаре» все термины, которые соответствуют запросу. Если совпадений больше 1024 (по умолчанию), генерируется исключение TooManyClauses-Exception.

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

Справочная страница API TooManyClauses показывает, что PrefixQuery, FuzzyQuery, WildcardQuery и RangeQuery расширяются таким образом (в BooleanQuery). Поскольку он находится в справочнике по API, это должно быть поведение, на которое пользователи могут положиться. Lucene не устанавливает произвольных ограничений на количество совпадений (кроме идентификатора документа, являющегося int), поэтому исключение «слишком много совпадений» может не иметь смысла. Возможно, PrefixQuery.rewrite (IndexReader) должен перехватить TooManyClauses и выдать исключение «слишком много префиксов», но сейчас это не так.

Кстати, еще один способ поиска по префиксу - использовать PrefixFilter. Либо отфильтруйте свой запрос с его помощью, либо оберните фильтр с помощью ConstantScoreQuery.