Использование Lucene для поиска адресов электронной почты

Я хочу использовать Lucene (в частности, Lucene.NET) для поиска доменов адресов электронной почты.

Например, я хочу найти "@ gmail.com", чтобы найти все электронные письма, отправленные на адрес электронной почты.

Выполнение запроса Lucene для «*@gmail.com» приводит к ошибке, звездочки не могут быть в начале запросов. Выполнение запроса для "@ gmail.com" не возвращает совпадений, поскольку "foo@gmail.com" рассматривается как целое слово, и вы не можете искать только части слова.

Как я могу это сделать?

20.08.2008 22:44:17
4 ОТВЕТА
РЕШЕНИЕ

Никто не дал удовлетворительного ответа, поэтому мы начали осматривать документацию 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);
12
21.08.2008 21:52:02
Я также пропустил бы токенайзер через LowerCaseFilter или, возможно, настроенный LowerCaseFilter, который будет только нижним регистром токена @ GmAil.COM
Ken Egozi 7.05.2014 06:33:45

Я вижу, у вас есть ваше решение, но мое могло бы избежать этого и добавить к документам, которые вы индексируете, поле с именем email_domain, в которое я бы добавил разобранный домен адреса электронной почты. Это может показаться глупым, но объем хранилища, связанный с этим, довольно минимален. Если вы хотите стать более любопытным, скажем, в каком-то домене было много поддоменов, вместо этого вы могли бы создать поле, в которое перешел обратный домен, чтобы хранить com.gmail, com.company.department или ae.eim, чтобы вы могли найти все адреса, связанные с Объединенными Арабскими Эмиратами, с префиксным запросом «ae».

5
22.08.2008 21:07:01

Вы можете выделить отдельное поле, которое индексирует обратный адрес электронной почты: Index 'foo@gmail.com' как 'moc.liamg@oof', что позволяет вам сделать запрос для "moc.liamg@*"

0
17.09.2008 14:13:41
Хм. Это звучит по-настоящему хакерски.
Judah Gabriel Himango 5.10.2008 21:15:13

Там же есть setAllowLeadingWildcard

Но будь осторожен . Это может привести к очень высокой производительности (поэтому по умолчанию оно отключено). Может быть, в некоторых случаях это было бы простым решением, но я бы предпочел использовать собственный токенизатор, как было сказано Джудой Химанго .

2
23.05.2017 12:13:34