Frage

Mit Hibernate Search Anmerkungen (meist nur @Field(index = Index.TOKENIZED)) Ich habe eine Reihe von Feldern zu einer persistenten Klasse von mir genannten Verbindung im Zusammenhang indiziert. Ich habe Setup-Textsuche über alle indizierten Felder, die MultiFieldQueryParser , die bisher funktionierte gut hat.

Unter den Feldern indiziert und durchsuchbar ist ein Feld Compound, mit Beispielwerten genannt:

  • 3-Hydroxyflavone
  • 6,4'-Dihydroxyflavone

Wenn ich für eine dieser beiden Werte in vollem Umfang suchen die zugehörige Verbindung Instanzen zurückgegeben. Jedoch Probleme treten auf, wenn ich den Teil-Namen verwenden und stellen Platzhalter:

  • für 3-Hydroxyflav* Suche gibt immer noch den richtigen Hit, aber
  • für 6,4'-Dihydroxyflav* Suche fehlschlägt, etwas zu finden.

Nun, wie ich ganz neu bin auf Lucene / Hibernate-Suche, ich bin nicht ganz sicher, wo an dieser Stelle zu suchen .. Ich denke, es ist etwas haben könnte, mit dem ' in der zweiten Abfrage zu tun, aber ich weiß nicht, wie es weitergehen .. sollte ich in Tokenizer / Analysatoren / QueryParsers oder etwas ganz anderes?

Oder kann mir jemand sagen, wie ich den zweiter bekommen kann Wildcard entsprechen suchen, vorzugsweise ohne das Verhalten Mehrfeldsuche zu brechen?

Ich bin mit Hibernate-Suche 3.1.0.GA & Lucene-Core 2.9.3.


Einig relevanten Codebits meinen aktuellen Ansatz zu verdeutlichen:

Relevante Teile der indizierten Verbindung Klasse:

@Entity
@Indexed
@Data
@EqualsAndHashCode(callSuper = false, of = { "inchikey" })
public class Compound extends DomainObject {
    @NaturalId
    @NotEmpty
    @Length(max = 30)
    @Field(index = Index.TOKENIZED)
    private String                  inchikey;

    @ManyToOne
    @IndexedEmbedded
    private ChemicalClass           chemicalClass;

    @Field(index = Index.TOKENIZED)
    private String                  commonName;
...
}

Wie kann ich zur Zeit die indizierten Felder suchen über:

String[] searchfields = Compound.getSearchfields();
MultiFieldQueryParser parser = 
    new MultiFieldQueryParser(Version.LUCENE_29, searchfields, new StandardAnalyzer(Version.LUCENE_29));
FullTextSession fullTextSession = Search.getFullTextSession(getSession());
FullTextQuery fullTextQuery = 
    fullTextSession.createFullTextQuery(parser.parse("searchterms"), Compound.class);
List<Compound> hits = fullTextQuery.list();
War es hilfreich?

Lösung

Ich denke, Ihr Problem ist eine Kombination aus Analysator und Abfragesprache Problemen. Es ist schwer zu sagen, was genau das Problem verursacht. Um das herauszufinden empfehle ich Ihnen, überprüfen Sie Index mit dem Lucene Index-Tool Luke .

Da in Ihrem Hibernate Search Konfiguration Sie nicht einem benutzerdefinierten Analysator den den Standard verwenden - StandardAnalyzer - verwendet wird. Dies wäre konsistent mit der Tatsache sein, dass Sie mit StandardAnalyzer im Konstruktor von MultiFieldQueryParser (immer den gleichen Analysator für die Indizierung verwenden und die Suche!). Was ich bin nicht so sicher ist, wie „6,4'-Dihydroxyflavon“ Token aufgeteilt wird von StandardAnalyzer . Dass das erste, was müssen Sie herausfinden. Zum Beispiel sagt die javadoc:

Splits Worte Bindestriche, es sei denn, es gibt eine Zahl in dem Token, in dieser Fall wird die gesamte Token als Produktnummer und wird interpretiert nicht gespalten.

Es könnte sein, dass Sie benötigen, um Ihre eigenen Analysator zu schreiben, die Ihre chemischen Namen die Art und Weise tokenizes Sie es für Ihre Anwendungsfälle benötigen.

Als nächstes wird der Abfrage-Parser. Stellen Sie sicher, dass Sie die Abfragesyntax verstehen - Lucene Abfragesyntax . Einige Zeichen haben eine besondere Bedeutung, zum Beispiel ein ‚-‘. Es könnte sein, dass Ihre Abfrage die falsche Art und Weise analysiert wird.

So oder so, erster Schritt o, um herauszufinden, wie Sie Ihr chemischer Name Token versehen lassen. Ich hoffe, das hilft.

Andere Tipps

Verwenden WhitespaceAnalyzer statt StandardAnalyzer. Es wird nur bei Leerzeichen aufgeteilt, und nicht bei Kommas, Bindestriche usw. (Es wird sie allerdings nicht klein geschrieben, so müssen Sie Ihre eigene Kette von Leerzeichen + Klein bauen, vorausgesetzt, Sie möchten, dass Ihre Suche Groß- und Kleinschreibung sein). Wenn Sie die Dinge anders für verschiedene Bereiche tun müssen, können Sie eine PerFieldAnalyzer verwenden.

Sie können nicht nur setzen Sie ihn auf un-Token versehen, denn das wird den ganzen Körper des Textes als ein Zeichen interpretiert werden.

ich meine eigenen Analysator schrieb:

import java.util.Set;
import java.util.regex.Pattern;

import org.apache.lucene.index.memory.PatternAnalyzer;
import org.apache.lucene.util.Version;

public class ChemicalNameAnalyzer extends PatternAnalyzer {

    private static Version version = Version.LUCENE_29;
    private static Pattern pattern = compilePattern();
    private static boolean toLowerCase = true;
    private static Set stopWords = null;

    public ChemicalNameAnalyzer(){
        super(version, pattern, toLowerCase, stopWords);
    }

    public static Pattern compilePattern() {
        StringBuilder sb =  new StringBuilder();
        sb.append("(-{0,1}\\(-{0,1})");//Matches an optional dash followed by an opening round bracket followed by an optional dash  
        sb.append("|");//"OR" (regex alternation)
        sb.append("(-{0,1}\\)-{0,1})"); 
        sb.append("|");//"OR" (regex alternation)
        sb.append("((?<=([a-zA-Z]{2,}))-(?=([^a-zA-Z])))");//Matches a dash ("-") preceded by two or more letters and succeeded by a non-letter
        return Pattern.compile(sb.toString());
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top