2008-08-20 7 views
5

Ich möchte Lucene (insbesondere Lucene.NET) verwenden, um nach E-Mail-Adressdomänen zu suchen.Verwenden von Lucene zum Suchen nach E-Mail-Adressen

z. Ich möchte nach "@ gmail.com" suchen, um alle E-Mails zu finden, die an eine Google Mail-Adresse gesendet werden.

Das Ausführen einer Lucene-Abfrage nach "*@gmail.com" führt zu einem Fehler, Sternchen können nicht am Anfang von Abfragen stehen. Wenn Sie eine Abfrage für "@ gmail.com" ausführen, werden keine Übereinstimmungen zurückgegeben, da "[email protected]" als ganzes Wort angezeigt wird und Sie nicht nach Teilen eines Worts suchen können.

Wie kann ich das tun?

Antwort

10

Niemand gab eine befriedigende Antwort, also begannen wir, in der Lucene-Dokumentation herumzustochern und stellten fest, dass wir dies mit benutzerdefinierten Analysatoren und Tokenizern erreichen konnten.

Die Antwort lautet wie folgt: Erstellen Sie einen WhitespaceAndAtSymbolTokenizer und einen WhitespaceAndAtSymbolAnalyzer und erstellen Sie dann Ihren Index mit diesem Analysator neu. Sobald Sie dies tun, wird eine Suche nach "@ gmail.com" alle Google Mail-Adressen zurückgeben, da es dank des Tokenizers, den wir gerade erstellt haben, als separates Wort angesehen wird.

Hier ist der Quellcode, es ist eigentlich sehr einfach ist:

class WhitespaceAndAtSymbolTokenizer : CharTokenizer 
{ 
    public WhitespaceAndAtSymbolTokenizer(TextReader input) 
     : base(input) 
    { 
    } 

    protected override bool IsTokenChar(char c) 
    { 
     // Make whitespace characters and the @ symbol be indicators of new words. 
     return !(char.IsWhiteSpace(c) || c == '@'); 
    } 
} 


internal class WhitespaceAndAtSymbolAnalyzer : Analyzer 
{ 
    public override TokenStream TokenStream(string fieldName, TextReader reader) 
    { 
     return new WhitespaceAndAtSymbolTokenizer(reader); 
    } 
} 

Das ist es! Jetzt müssen Sie nur Ihren Index neu erstellen und alle Suchvorgänge mit diesem neuen Analyzer durchführen. Zum Beispiel Dokumente zu Ihrem Index schreiben:

IndexWriter index = new IndexWriter(indexDirectory, new WhitespaceAndAtSymbolAnalyzer()); 
index.AddDocument(myDocument); 

Suchen durchführen sollen auch den Analysator verwenden:

IndexSearcher searcher = new IndexSearcher(indexDirectory); 
Query query = new QueryParser("TheFieldNameToSearch", new WhitespaceAndAtSymbolAnalyzer()).Parse("@gmail.com"); 
Hits hits = query.Search(query); 
+0

Ich würde auch den Tokenizer durch einen LowerCaseFilter übergeben, oder vielleicht einen benutzerdefinierten LowerCaseFilter, der nur das Token @ GmAil.COM –

5

Ich sehe Sie Ihre Lösung haben, aber ich hätte die vermieden und fügte ein Feld zu den Dokumenten, die Sie indizieren, namens email_domain, in die ich die herausgefilterte Domäne der E-Mail-Adresse hinzugefügt hätte. Es klingt vielleicht albern, aber die damit verbundene Speicherkapazität ist ziemlich gering. Wenn Sie Lust haben, schicker zu werden, sagen Sie, einige Domains hätten viele Subdomains, könnten Sie stattdessen ein Feld erstellen, in das die umgekehrte Domaine geht, also würden Sie com.gmail, com.company.department oder ae.eim speichern, damit Sie es finden Alle Vereinigten Arabischen Emirate bezogen sich auf Adressen mit einer Präfix-Abfrage von 'ae'.

2

Es gibt auch setAllowLeadingWildcard

Aber vorsichtig sein. Dies könnte sehr teuer werden (deshalb ist es standardmäßig deaktiviert). Vielleicht wäre dies in einigen Fällen eine einfache Lösung, aber ich würde auch einen benutzerdefinierten Tokenizer bevorzugen, wie von Judah Himango angegeben.