关于.net:使用Lucene搜索电子邮件地址

关于.net:使用Lucene搜索电子邮件地址

Using Lucene to search for email addresses

我想使用Lucene(尤其是Lucene.NET)搜索电子邮件地址域。

例如。 我想搜索" @ gmail.com"以查找发送到gmail地址的所有电子邮件。

对" *@gmail.com"运行Lucene查询会导致错误,星号不能出现在查询开始处。 对" @ gmail.com"运行查询不会返回任何匹配项,因为" foo@gmail.com"被视为一个完整的单词,您不能仅搜索单词的一部分。

我怎样才能做到这一点?


没有人给出令人满意的答案,因此我们开始浏览Lucene文档,发现可以使用自定义分析器和Tokenizer实现此目的。

答案是这样的:创建一个WhitespaceAndAtSymbolTokenizer和WhitespaceAndAtSymbolAnalyzer,然后使用此分析器重新创建索引。完成此操作后,搜索" @ gmail.com"将返回所有gmail地址,因为我们刚刚创建的令牌生成器将其视为一个单独的单词。

这是源代码,实际上非常简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);
    }
}

而已!现在,您只需要重建索引并使用此新的Analyzer进行所有搜索。例如,将文档写入索引:

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

执行搜索也应使用分析仪:

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

我看到您有解决方案,但是我会避免这种情况,并在要建立索引的文档中添加一个名为email_domain的字段,在该字段中我将添加已解析出的电子邮件地址域。听起来可能很愚蠢,但是与此相关的存储量却很小。如果您想变得更高级,例如说某个域包含许多子域,则可以改个字段来创建反向域,以便存储com.gmail,com.company.department或ae.eim,以便找到所有阿拉伯联合酋长国的相关地址,其前缀查询为" ae"。


还有setAllowLeadingWildcard

但小心点。这可能会使性能变得非常昂贵(这就是为什么默认情况下禁用它的原因)。也许在某些情况下这将是一个简单的解决方案,但我也希望像Judah Himango所说的那样使用自定义令牌生成器。


您可以使用一个单独的字段来索引反向的电子邮件地址:
将'foo@gmail.com'索引为'moc.liamg@oof'
这使您可以查询" moc.liamg@*"


推荐阅读