2013-04-15 3 views
1

La version utilisée de Lucene (Java) est 4.2.1 et l'analyseur utilisé pour l'indexation et la recherche est org.apache.lucene.analysis.core.WhitespaceAnalyzer. Le code ci-dessous est en Scala mais je pense qu'il est facile à lire pour tous ceux qui ont l'expérience d'un langage semblable à C.Indexer et rechercher des caractères non-alpha dans Lucene Java

Voici le problème: J'ai besoin d'indexer et de rechercher du texte avec des caractères non-alpha. Par exemple j'ai des entités avec des noms: "nom 1", "nom 2", "nom 3", ... et j'aimerais pouvoir chercher "nom 2" ou simplement "2" ou même "moi" 2 ".

Jusqu'à présent, j'ai

le terrain:

val textField = new TextField("text", theFullText, Field.Store.NO) 

et la requête:

val parser = new QueryParser(version, "text", analyzer) 

// case-sensitive search 
parser.setLowercaseExpandedTerms(false) // removed when MyAnalyzer is used 

// To be able to search for text in the middle. Makes searches slower when the index is big! 
parser.setAllowLeadingWildcard(true) 

val textWithWildcard = s"*${QueryParserBase.escape(text)}*" 

val textQuery = parser.parse(textWithWildcard) 
booleanQuery.add(textQuery, BooleanClause.Occur.MUST) 
val topDocs: TopDocs = searcher.search(booleanQuery, 9999) 
val hits: Array[ScoreDoc] = topDocs.scoreDocs 
hits.map(_.doc) // return an Array of ScoreDocs' ids 

Un simple test unitaire:

"be able to search numbers" { 
    for (idx <- 1 to 10) { 
    val entity = new Entity 
    entity.id = idx 
    entity.name = s"name ${idx}" 

    indexingService.index(entity) 
    } 


    val ids: Seq[Int] = indexingService.search[Entity]("name 3") 
    ids.length must_==(1) 
} 

-à-dire la création de 10 entités et alors chercher le th Troisième. Le problème est que le résultat est 0.

Idées que changer dans ma configuration pour le faire fonctionner?

Mise à jour: J'ai créé mon propre analyseur pour être en mesure de soutenir la recherche insensible à la casse:

class MyAnalyzer(ver: Version) extends Analyzer { 

    protected def createComponents(fieldName: String, reader: Reader): Analyzer.TokenStreamComponents = { 
     val tokenizer = new WhitespaceTokenizer(ver, reader) 
     val lowerCaseFilter = new LowerCaseFilter(ver, tokenizer) 
     val tsc = new Analyzer.TokenStreamComponents(tokenizer, lowerCaseFilter) 
     tsc 
    } 
} 

Et maintenant, le résultat est ! Encore une fois, ceci n'est pas souhaité parce que le test recherche "nom 3" mais toutes les entités sont renvoyées, c'est-à-dire qu'il semble que les nombres sont coupés à la fois à l'index et à la recherche.

+0

Pouvez-vous sauvegarder 'booleanQuery' dans System.out? – mschonaker

+0

Le voici: + (texte: * nom du texte: 3 *) –

Répondre

0

La solution était d'ajouter:

parser.setDefaultOperator(Operator.AND) 

Je l'ai essayé plus tôt et cela n'a pas fonctionné pour une raison quelconque. Je suppose que d'autres paramètres étaient problématiques.

0

Pour rechercher un groupe de mots dans un champ, entourez les mots de guillemets. Je crois que vous pouvez ignorer les caractères génériques (il n'y a rien entre le nom et 3).

val textWithWildcard = s"\"${QueryParserBase.escape(text)}\"" 

Modifier: Donner 10 résultats est le comportement correct étant donné que les documents retournés ont des scores différents. Vous devez pouvoir faire la distinction entre une requête de correspondance exacte et une requête partielle lorsque vous effectuez une recherche par entité.

+0

Entourer de guillemets ne change pas les résultats de 10. Je pense que j'ai besoin des caractères génériques car je veux être en mesure d'utiliser la ligne de terme de recherche "moi "où" moi "est contenu dans" nom ". Je ne vous suis pas dans l'explication pourquoi le résultat est 10. Pourquoi chercher "nom 3" retournera le document avec "nom 4"? C'est ce que j'essaie d'accomplir - la recherche de "nom 4" devrait renvoyer un résultat, la recherche de "nom 1" devrait renvoyer 2 résultats ("nom 1" et "nom 10"). –

+0

Vous obtenez dix résultats parce que vous obtenez un hit partiel sur "name" (en raison de la clause "OR" par défaut et du WhiteSpaceAnalyzer), mais vous l'avez déjà compris vous-même. –

Questions connexes