2008-08-20 17 views
5

Desidero utilizzare Lucene (in particolare, Lucene.NET) per cercare domini di indirizzi e-mail.Utilizzo di Lucene per cercare gli indirizzi e-mail

E.g. Voglio cercare "@ gmail.com" per trovare tutte le email inviate a un indirizzo Gmail.

L'esecuzione di una query Lucene per "*@gmail.com" genera un errore, gli asterischi non possono trovarsi all'inizio delle query. L'esecuzione di una query per "@ gmail.com" non restituisce corrispondenze, perché "[email protected]" è visto come una parola intera e non è possibile cercare solo parti di una parola.

Come posso fare questo?

risposta

10

Nessuno ha dato una risposta soddisfacente, quindi abbiamo iniziato a dare un'occhiata alla documentazione di Lucene e abbiamo scoperto che siamo in grado di farlo utilizzando Analizzatori e Tokenizzatori personalizzati.

La risposta è questa: creare un WhitespaceAndAtSymbolTokenizer e un WhitespaceAndAtSymbolAnalyzer, quindi ricreare il proprio indice utilizzando questo analizzatore. Una volta eseguita questa operazione, la ricerca di "@ gmail.com" restituirà tutti gli indirizzi Gmail, perché è vista come una parola separata grazie al Tokenizer appena creato.

Ecco il codice sorgente, in realtà è molto semplice:

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); 
    } 
} 

Questo è tutto! Ora hai solo bisogno di ricostruire il tuo indice e fare tutte le ricerche usando questo nuovo Analyzer. Ad esempio, per scrivere documenti per l'indice:

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

ricerche Performing dovrebbero usare l'analizzatore così:

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

Passerei anche il tokenizer attraverso un LowerCaseFilter, o forse un LowerCaseFilter personalizzato che avrebbe solo in minuscolo il token @ GmAil.COM –

5

Vedo che hai la soluzione, ma la mia sarebbe evitato questo e ha aggiunto un campo ai documenti che stai indicizzando chiamato email_dominio, in cui avrei aggiunto il dominio analizzato dell'indirizzo email. Potrebbe sembrare sciocco, ma la quantità di spazio di archiviazione associata a questo è piuttosto ridotta. Se hai voglia di crescere, dire che alcuni domini hanno molti sottodomini, potresti invece creare un campo in cui è stato eseguito il dominio inverso, quindi memorizzerai com.gmail, com.company.department o ae.eim in modo da poter trovare tutti gli indirizzi relativi agli Emirati Arabi Uniti con una domanda prefissata di "ae".

2

C'è anche setAllowLeadingWildcard

Ma attenzione. Questo potrebbe ottenere molto costose prestazioni (questo è il motivo per cui è disabilitato di default). Forse in alcuni casi questa sarebbe una soluzione semplice, ma preferirei un Tokenizer personalizzato come indicato da Judah Himango.

Problemi correlati