Использование Lucene для поиска адресов электронной почты - PullRequest
6 голосов
/ 21 августа 2008

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

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

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

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

Ответы [ 4 ]

12 голосов
/ 21 августа 2008

Никто не дал удовлетворительного ответа, поэтому мы начали осматривать документацию 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);
5 голосов
/ 23 августа 2008

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

2 голосов
/ 19 сентября 2008

Там также есть setAllowLeadingWildcard

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

0 голосов
/ 17 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...