Pergunta

Quero usar o Lucene (em particular, Lucene.NET) para pesquisar domínios de endereços de e-mail.

Por exemplo.Quero pesquisar "@gmail.com" para encontrar todos os emails enviados para um endereço do Gmail.

Executar uma consulta Lucene para "*@gmail.com" resulta em um erro, os asteriscos não podem estar no início das consultas.Executar uma consulta para "@gmail.com" não retorna nenhuma correspondência, porque "foo@gmail.com" é visto como uma palavra inteira e você não pode pesquisar apenas partes de uma palavra.

Como posso fazer isso?

Foi útil?

Solução

Ninguém deu uma resposta satisfatória, então começamos a vasculhar a documentação do Lucene e descobrimos que podemos fazer isso usando analisadores e tokenizadores personalizados.

A resposta é esta:crie um WhitespaceAndAtSymbolTokenizer e um WhitespaceAndAtSymbolAnalyzer e, em seguida, recrie seu índice usando este analisador.Depois de fazer isso, uma pesquisa por “@gmail.com” retornará todos os endereços do Gmail, porque é visto como uma palavra separada graças ao Tokenizer que acabamos de criar.

Aqui está o código fonte, na verdade é muito simples:

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

É isso!Agora você só precisa reconstruir seu índice e fazer todas as pesquisas usando este novo Analisador.Por exemplo, para gravar documentos no seu índice:

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

A realização de pesquisas também deve usar o analisador:

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

Outras dicas

Vejo que você tem sua solução, mas a minha teria evitado isso e adicionado um campo aos documentos que você está indexando chamado email_domain, ao qual eu teria adicionado o domínio analisado do endereço de e-mail.Pode parecer bobagem, mas a quantidade de armazenamento associada a isso é mínima.Se você quiser ser mais sofisticado, digamos que algum domínio tenha muitos subdomínios, você pode, em vez disso, criar um campo no qual o domínio invertido foi, para armazenar com.gmail, com.empresa.departamento ou ae.eim para encontrar todos os endereços relacionados aos Emirados Árabes Unidos com uma consulta de prefixo 'ae.'

Também há setAllowLeadingWildcard

Mas seja cuidadoso.Isso pode custar muito caro em termos de desempenho (é por isso que está desabilitado por padrão).Talvez em alguns casos esta seja uma solução fácil, mas eu preferiria um Tokenizer personalizado conforme indicado por Judá Himango, também.

Você poderia ter um campo separado que indexasse o endereço de e-mail invertido:Índice 'foo@gmail.com' como 'moc.liamg@oof', que permite fazer uma consulta para "moc.liamg@*"

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top