Question

Lors de mes tests, je me suis soudainement heurté à une exception Too Many Clauses lorsque j'essayais d'obtenir les résultats d'une requête booléenne consistant en une requête term et une requête générique.

J'ai effectué une recherche sur le réseau et sur les ressources trouvées qu'ils suggèrent d'augmenter BooleanQuery.SetMaxClauseCount ().
Cela me semble louche. À quoi devrais-je m'adresser? Comment puis-je compter que ce nouveau nombre magique suffira à ma requête? Jusqu'où puis-je augmenter ce nombre avant que tout l'enfer se déchaîne?

En général, j'estime que ce n'est pas une solution. Il doit y avoir un problème plus profond.

La requête était + {+ companyName: mercedes + paintCode: a *} et l'index contient ~ 2,5 millions de documents.

Était-ce utile?

La solution

le paintCode: une * partie de la requête est une requête préfixe pour tout paintCode commençant par un "a". Est-ce ce que vous visez?

Lucene développe les requêtes de préfixe en une requête booléenne contenant tous les termes possibles qui correspondent au préfixe. Dans votre cas, apparemment, il y a plus de 1024 paintCode possibles qui commencent par un "a".

S'il vous semble que les requêtes avec préfixes sont inutiles, vous n'êtes pas loin de la vérité.

Je vous suggérerais de modifier votre schéma d'indexation afin d'éviter d'utiliser une requête de préfixe. Je ne suis pas sûr de ce que vous essayez d'accomplir avec votre exemple, mais si vous souhaitez rechercher les codes de peinture par la première lettre, créez un champ paintCodeFirstLetter et effectuez une recherche en fonction de ce champ.

ajouté

Si vous êtes désespéré et souhaitez accepter des résultats partiels, vous pouvez créer votre propre version de Lucene à partir du code source. Vous devez modifier les fichiers PrefixQuery.java et MultiTermQuery.java , les deux sous org / apache / lucene / search . Dans la méthode rewrite des deux classes, modifiez la ligne

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

à

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

Je l'ai fait pour mon propre projet et cela fonctionne.

Si vous n'aimez vraiment pas l'idée de changer Lucene, vous pouvez écrire votre propre variante PrefixQuery et votre propre QueryParser, mais je ne pense pas que ce soit beaucoup mieux.

Autres conseils

Il semble que vous utilisez ceci sur un champ qui est en quelque sorte du type Mot-clé (ce qui signifie qu'il n'y aura pas plusieurs jetons dans votre champ de source de données).

Voici une suggestion qui me semble assez élégante: http://grokbase.com/t/lucene.apache.org/java-user/2007/11/substring-indexing-toavoid-toavoid-toomanyclauses-exception/ 12f7s7kzp2emktbn66tdmfpcxfya

L'idée de base est de décomposer votre terme en plusieurs champs de plus en plus longs jusqu'à ce que vous soyez certain de ne pas atteindre la limite de clause.

Exemple:

Imaginez un paintCode comme celui-ci:

"a4c2d3"

Lors de l'indexation de cette valeur, vous créez les valeurs de champ suivantes dans votre document:

[paintCode]: "a4c2d3"

[paintCode1n]: "a"

[paintCode2n]: "a4"

[paintCode3n]: "a4c"

Au moment où vous interrogez, le nombre de caractères de votre terme détermine le champ à rechercher. Cela signifie que vous exécuterez une requête préfixe uniquement pour les termes de plus de 3 caractères, ce qui réduira considérablement le nombre de résultats internes, empêchant ainsi la fameuse TooManyBooleanClausesException . Apparemment, cela accélère également le processus de recherche.

Vous pouvez facilement automatiser un processus qui décompose les termes automatiquement et remplit les documents avec des valeurs selon un schéma de noms lors de l'indexation.

Certains problèmes peuvent survenir si vous avez plusieurs jetons pour chaque champ. Vous pouvez trouver plus de détails dans l'article

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top