2008-08-20 16 views
5

Chcę używać Lucene (w szczególności Lucene.NET) do wyszukiwania domen adresów e-mail.Używanie Lucene do wyszukiwania adresów e-mailowych

E.g. Chcę wyszukać "@ gmail.com", aby znaleźć wszystkie wiadomości e-mail wysłane na adres Gmail.

Uruchomienie zapytania Lucene dla "*@gmail.com" powoduje błąd, a gwiazdki nie mogą być na początku zapytania. Uruchamianie zapytania dla "@ gmail.com" nie zwraca żadnych dopasowań, ponieważ "[email protected]" jest postrzegane jako całe słowo i nie można wyszukiwać tylko części wyrazu.

Jak mogę to zrobić?

Odpowiedz

10

Nikt nie udzielił zadowalającej odpowiedzi, więc zaczęliśmy szperać w dokumentacji Lucene i odkryliśmy, że możemy to zrobić za pomocą niestandardowych analizatorów i tokenizerów.

Odpowiedź jest następująca: utwórz WhitespaceAndAtSymbolTokenizer i WhitespaceAndAtSymbolAnalyzer, a następnie utwórz indeks za pomocą tego analizatora. Gdy to zrobisz, wyszukiwanie "@ gmail.com" zwróci wszystkie adresy w Gmailu, ponieważ jest to oddzielne słowo dzięki utworzonemu przez nas Tokenizerowi.

Oto kod źródłowy, to faktycznie bardzo prosta:

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

To jest to! Teraz wystarczy przebudować swój indeks i wykonać wszystkie wyszukiwania przy użyciu tego nowego analizatora. Na przykład, aby zapisywać dokumenty do indeksu:

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

wyszukiwania sceniczne powinny używać analizatora, a także:

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

Mogę również przekazać tokenizator przez LowerCaseFilter lub niestandardowy LowerCaseFilter, który będzie tylko mały znacznik @ GmAil.COM –

5

widzę masz rozwiązanie, ale kopalnia byłoby uniknąć tego i dodaje pole do indeksowanych dokumentów o nazwie email_domain, do których dodałbym przeanalizowaną domenę adresu e-mail. To może zabrzmieć głupio, ale ilość pamięci związanej z tym jest całkiem minimalna. Jeśli masz ochotę stać się bardziej doświadczonym, powiedzmy, że niektóre domeny mają wiele subdomen, możesz zamiast tego utworzyć pole, w którym znajduje się odwrócona domena, więc możesz przechowywać com.gmail, com.company.department lub ae.eim, abyś mógł znaleźć wszystkie adresy powiązane Zjednoczone Emiraty Arabskie z zapytaniem prefiksowym "ae".

2

Istnieje również setAllowLeadingWildcard

Ale ostrożny. Może to bardzo kosztować wydajność (dlatego domyślnie jest wyłączona). Może w niektórych przypadkach byłoby to łatwe rozwiązanie, ale wolałbym niestandardowy Tokenizer, o którym wspomniał także Judah Himango.

Powiązane problemy