Использование Lucene для поиска адресов электронной почты
Вопрос
Я хочу использовать 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@*".