Domanda

Voglio utilizzare Lucene (in particolare Lucene.NET) per cercare domini di indirizzi e-mail.

Per esempio.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 alcuna corrispondenza, perché "foo@gmail.com" viene visto come una parola intera e non è possibile cercare solo parti di una parola.

Come posso fare questo?

È stato utile?

Soluzione

Nessuno ha dato una risposta soddisfacente, quindi abbiamo iniziato a consultare la documentazione di Lucene e abbiamo scoperto che possiamo ottenere questo risultato utilizzando analizzatori e tokenizzatori personalizzati.

La risposta è questa:crea un WhitespaceAndAtSymbolTokenizer e un WhitespaceAndAtSymbolAnalyzer, quindi ricrea il tuo indice utilizzando questo analizzatore.Una volta fatto ciò, la ricerca di "@gmail.com" restituirà tutti gli indirizzi Gmail, perché è visto come una parola separata grazie al Tokenizer che abbiamo 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 devi solo ricostruire il tuo indice ed eseguire tutte le ricerche utilizzando questo nuovo analizzatore.Ad esempio, per scrivere documenti nel tuo indice:

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

Anche l'esecuzione delle ricerche dovrebbe utilizzare l'analizzatore:

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

Altri suggerimenti

Vedo che hai la tua soluzione, ma la mia l'avrebbe evitato e avrebbe aggiunto un campo ai documenti che stai indicizzando chiamato email_domain, in cui avrei aggiunto il dominio analizzato dell'indirizzo email.Potrebbe sembrare sciocco, ma la quantità di spazio di archiviazione associata a questo è piuttosto minima.Se hai voglia di diventare più elaborato, supponiamo che un dominio abbia molti sottodomini, potresti invece creare un campo in cui inserire il dominio invertito, quindi memorizzeresti com.gmail, com.company.department o ae.eim in modo da poter trovare tutti gli indirizzi relativi agli Emirati Arabi Uniti con una query di prefisso "ae".

C'è anche setAllowLeadingWildcard

Ma sii attento.Ciò potrebbe costare molto in termini di prestazioni (ecco perché è disabilitato per impostazione predefinita).Forse in alcuni casi questa sarebbe una soluzione semplice, ma preferirei un Tokenizer personalizzato come affermato da Giuda Himango, pure.

Potresti creare un campo separato che indicizzi l'indirizzo email invertito:INDICE 'foo@gmail.com' come 'moc.liamg@oof' che ti consente di fare una query per "moc.liamg@*"

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top