2008-08-20 51 views
5

我想使用Lucene(特別是Lucene.NET)來搜索電子郵件地址域。使用Lucene搜索電子郵件地址

E.g.我想搜索「@ gmail.com」以查找發送到Gmail地址的所有電子郵件。

對「*@gmail.com」運行Lucene查詢會導致錯誤,星號不能位於查詢開始處。對「@ gmail.com」運行查詢不會返回任何匹配項,因爲「[email protected]」被看作是一個完整的單詞,而且您無法只搜索單詞的某些部分。

我該怎麼做?

回答

10

沒有人給出滿意的答案,所以我們開始圍繞Lucene文檔進行探索,並發現我們可以使用自定義分析器和標記器完成此操作。

答案是這樣的:創建一個WhitespaceAndAtSymbolTokenizer和一個WhitespaceAndAtSymbolAnalyzer,然後使用這個分析器重新創建索引。一旦你這樣做了,搜索「@ gmail.com」將會返回所有的gmail地址,因爲它被看作是一個單獨的詞,這要感謝我們剛剛創建的Tokenizer。

這裏的源代碼,但實際上非常簡單:

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

這就是它!現在您只需重建索引並使用此新分析器進行所有搜索。例如,寫文件索引:

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

執行搜索應該使用分析器,以及:

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

我也通過一個LowerCaseFilter,或者可能是一個自定義的LowerCaseFilter,只會將@ GmAil.COM標記 – 2014-05-07 06:33:45

5

我看到你有你的解決方案,但我會避免這一點,並添加一個字段到您要編入索引的文件稱爲email_domain,我將其中添加解析出的電子郵件地址域。這可能聽起來很愚蠢,但與此相關的存儲量非常少。如果你覺得自己變得更加奇特,比如說某個域名有許多子域名,那麼你可以創建一個反向域名所在的域名,這樣你就可以存儲com.gmail,com.company.department或ae.eim,這樣你就可以找到所有與阿拉伯聯合酋長國有關的地址的前綴查詢爲'ae'。

2

也有setAllowLeadingWildcard

但要小心。這可能會使性能非常昂貴(這就是爲什麼它在默認情況下被禁用)。也許在某些情況下,這將是一個簡單的解決方案,但我更喜歡Judah Himango所述的自定義Tokenizer。