2009-10-07 10 views
15

J'ai deux ensembles d'index de recherche. TestIndex (utilisé dans notre environnement de test) et ProdIndex (utilisé dans l'environnement PRODUCTION). Lucene requête de recherche: + date: [20090410184806 TO 20091007184806] fonctionne très bien pour l'index de test, mais donne ce message d'erreur pour Prod index.Aide nécessaire pour déterminer la raison pour laquelle maxClauseCount est défini sur 1024 erreur

« maxClauseCount est réglé sur 1024 »

Si j'exécutons la ligne suivante juste avant d'exécuter la requête de recherche, alors je ne comprends pas cette erreur. BooleanQuery.SetMaxClauseCount (Int16.MaxValue); searcher.Search (myQuery, collector);

Ai-je manqué quelque chose ici? Pourquoi ne pas obtenir cette erreur dans l'index de test? Le schéma pour deux index sont mêmes.Ils diffèrent seulement par rapport au nombre d'enregistrements/data.PROD index a un nombre plus élevé d'enregistrements (environ 1300) que ceux du premier test (vers 950).

Merci d'avoir lu.

+0

chk http://wiki.apache.org/lucene-java/LuceneFAQ#Why_am_I_getting_a_TooManyClauses_exception.3F – Narayan

Répondre

11

La requête de plage est essentiellement transformée en une requête booléenne avec une clause pour chaque valeur possible, ORed together.

Par exemple, le prix de requête +: [10 à 13] est à une requête transformés ne booléenne

+(price:10 price:11 price:12 price:13) 

en supposant que toutes les valeurs 10-13 existent dans l'index. Je suppose que toutes vos valeurs de 1300 se situent dans la fourchette que vous avez indiquée. Ainsi, la requête booléenne a 1300 clauses, ce qui est supérieur à la valeur par défaut de 1024. Dans l'index de test, la limite de 1024 n'est pas atteinte car il n'y a que 950 valeurs.

+0

Merci Shashikant pour votre réponse. Quelle est la solution pour résoudre ce problème? BooleanQuery.SetMaxClauseCount (Int16.MaxValue); est censé être un appel très coûteux. Merci. –

+1

L'inconvénient est la performance de la requête dégrade avec le nombre d'horodatages uniques. Mais, ce n'est pas si mal. Vous pouvez l'essayer et vérifier si la perfromance est acceptable. Vous devriez surtout bien aller. Lucene 2.9 (Java) a considérablement amélioré les requêtes de plage. Je ne suis pas sûr quand cela sera porté à la version .Net. En attendant, il existe d'autres astuces que vous pouvez utiliser pour les requêtes de date. Typiquement, cela implique de casser la date en année, mois et jour.Cela nécessite beaucoup de travail pour traduire la requête de l'utilisateur au format lucene sous-jacent. Essayez de chercher "Lucene date requête" pour obtenir des idées intéressantes. –

+0

En attendant, vous pouvez concevoir votre champ de date différemment - pourriez-vous le limiter à des jours en une seule année? (limitant ainsi à 365 valeurs)? Ou diviser une donnée en année, mois et jour et utiliser une requête plus complexe? Je sais que c'est inélégant, mais cela peut fonctionner. –

12

J'ai eu le même problème. Ma solution était d'attraper BooleanQuery.TooManyClauses et d'augmenter dynamiquement maxClauseCount.

Voici un code similaire à celui que j'ai en production.

Bonne chance, Randy


    private static Hits searchIndex(Searcher searcher, Query query) 
     throws IOException 
    { 
     boolean retry = true; 
     while (retry) 
     { 
      try 
      { 
       retry = false; 
       Hits myHits = searcher.search(query); 
       return myHits; 
      } 
      catch (BooleanQuery.TooManyClauses e) 
      { 
       // Double the number of boolean queries allowed. 
       // The default is in org.apache.lucene.search.BooleanQuery and is 1024. 
       String defaultQueries = Integer.toString(BooleanQuery.getMaxClauseCount()); 
       int oldQueries = Integer.parseInt(System.getProperty("org.apache.lucene.maxClauseCount", defaultQueries)); 
       int newQueries = oldQueries * 2; 
       log.error("Too many hits for query: " + oldQueries + ". Increasing to " + newQueries, e); 
       System.setProperty("org.apache.lucene.maxClauseCount", Integer.toString(newQueries)); 
       BooleanQuery.setMaxClauseCount(newQueries); 
       retry = true; 
      } 
     } 
    } 
+0

Ceci est une bonne solution, mais pourquoi ne pas compter les clauses avant cela et le régler correctement au lieu d'après attraper l'exception? Est-ce que cela affectera les performances si une grande quantité de données est en cours de traitement? – trillions

+1

Nanshi, la raison en est que cela * ne peut pas * être calculé. Il n'y a aucun moyen de savoir combien d'éléments sont inclus dans la plage jusqu'à * après * vous faites une requête, mais cette requête est ensuite transformée en une requête booléenne où l'exception est levée. –

+0

Merci Randy! J'ai un cas de différence que j'ai construit des requêtes booléennes moi-même, donc j'étais capable de le compter avant d'exécuter une recherche. – trillions

1

J'ai eu ce même problème dans le code C# en cours d'exécution avec le système de gestion de contenu Web Sitecore. J'ai utilisé la réponse de Randy ci-dessus, mais je n'ai pas pu utiliser la fonctionnalité de propriété System get and set. Au lieu de cela, j'ai récupéré le compte courant, l'ai incrémenté et rétabli. J'ai bien travaillé!

catch (BooleanQuery.TooManyClauses e) 
{ 
    // Increment the number of boolean queries allowed. 
    // The default is 1024. 
    var currMaxClause = BooleanQuery.GetMaxClauseCount(); 
    var newMaxClause = currMaxClause + 1024; 
    BooleanQuery.SetMaxClauseCount(newMaxClause); 
    retry = true; 
} 
0

Juste mis, BooleanQuery.setMaxClauseCount(Integer.MAX_VALUE); et c'est tout.

Questions connexes