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

StackOverflow https://stackoverflow.com/questions/19014

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

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

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

Это было полезно?

Решение

Никто не дал удовлетворительного ответа, поэтому мы начали копаться в документации Lucene и обнаружили, что можем добиться этого с помощью пользовательских анализаторов и токенизаторов.

Ответ заключается в следующем:создайте WhitespaceAndAtSymbolTokenizer и WhitespaceAndAtSymbolAnalyzer, затем воссоздайте свой индекс с помощью этого анализатора.Как только вы это сделаете, поиск по "@gmail.com" вернет все адреса gmail, потому что благодаря токенизатору, который мы только что создали, он воспринимается как отдельное слово.

Вот исходный код, на самом деле он очень прост:

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

Другие советы

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

Там также есть Установите Allowleadingwildcard

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top