2016-07-29 24 views
2

Ich habe eine Lucene-basierte Software implementiert, um mehr als 10 Millionen Personennamen zu indizieren, und diese Namen können auf verschiedene Arten wie "Luíz" und "Luis" geschrieben werden. Der Index wurde mithilfe der phonetischen Werte der jeweiligen Tokens erstellt (ein benutzerdefinierter Analysator wurde erstellt).Können wir SpanNearQuery im phonetischen Index verwenden?

Derzeit verwende ich QueryParser, um nach einem bestimmten Namen mit guten Ergebnissen abzufragen. Aber in dem Buch "Lucene in Action" wird erwähnt, dass SpanNearQuery meine Abfragen mithilfe der Nähe von Tokens verbessern kann. Ich habe mit der SpanNearQuery gegen einen nicht-phonetischen Index des Namens gespielt und die Ergebnisse waren im Vergleich zu QueryParser überlegen.

Da wir den gleichen Analysator verwendet, um die Indizierung abfragen sollten, kann ich nicht finden, wie ich meinen individuellen Laut Analysator und SpanNearQuery zur gleichen Zeit verwenden kann, oder Umformulierung:

how can I use SpanNearQuery on the phonetic index? 

Vielen Dank im Voraus.

Antwort

1

Mein erster Gedanke ist: Würde nicht eine Phrase Abfrage mit Slop die Arbeit machen? Das wäre sicherlich der einfachste Weg sein:

"term1 term2"~5 

Dies wird Ihren Laut Analysator verwenden, und eine Nähe Abfrage mit den daraus resultierenden Token erzeugen.


Also, wenn Sie wirklich Notwendigkeit tun SpanQueries hier zu verwenden (vielleicht sind Sie mit Fuzzy-Abfragen oder Platzhalter oder so, oder PhraseQuery drohend an Sie wurde leering und Sie wollen nichts mehr mit ihm zu tun), müssen Sie die Analyse selbst durchführen. Sie können dies tun, indem Sie einen TokenStream von Analyzer.tokenStream erhalten und die analysierten Token durchlaufen.

Wenn Sie einen Laut Algorithmus verwenden, die pro Trimester (soundex, zum Beispiel) einen einzigen Code erzeugt:

SpanNearQuery.Builder nearBuilder = new SpanNearQuery.Builder("text", true); 
nearBuilder.setSlop(4); 

TokenStream stream = analyzer.tokenStream("text", queryStringToParse); 
stream.addAttribute(CharTermAttribute.class); 
stream.reset(); 
while(stream.incrementToken()) { 
    CharTermAttribute token = stream.getAttribute(CharTermAttribute.class); 
    nearBuilder.addClause(new SpanTermQuery(new Term("text", token.toString()))); 
} 
Query finalQuery = nearBuilder.build(); 
stream.close(); 

Wenn Sie ein Doppel Metaphone verwenden, wo Sie 1-2 Begriffe auf die haben gleiche Position, es ist ein bisschen komplexer, da Sie diese Position Inkremente berücksichtigen müssen:

SpanNearQuery.Builder nearBuilder = new SpanNearQuery.Builder("text", true); 
nearBuilder.setSlop(4); 

TokenStream stream = analyzer.tokenStream("text", "through and through"); 
stream.addAttribute(CharTermAttribute.class); 
stream.addAttribute(PositionIncrementAttribute.class); 
stream.reset(); 
String queuedToken = null; 
while(stream.incrementToken()) { 
    CharTermAttribute token = stream.getAttribute(CharTermAttribute.class); 
    PositionIncrementAttribute increment = stream.getAttribute(PositionIncrementAttribute.class); 

    if (increment.getPositionIncrement() == 0) { 
     nearBuilder.addClause(new SpanOrQuery(
       new SpanTermQuery(new Term("text", queuedToken)), 
       new SpanTermQuery(new Term("text", token.toString())) 
       )); 
     queuedToken = null; 
    } 
    else if (increment.getPositionIncrement() >= 1 && queuedToken != null) { 
     nearBuilder.addClause(new SpanTermQuery(new Term("text", queuedToken))); 
     queuedToken = token.toString(); 
    } 
    else { 
     queuedToken = token.toString(); 
    } 
} 

if (queuedToken != null) { 
    nearBuilder.addClause(new SpanTermQuery(new Term("text", queuedToken))); 
} 

Query finalQuery = nearBuilder.build(); 
stream.close();