Pregunta

Quiero utilizar Lucene (en particular, Lucene.NET) para buscar dominios de direcciones de correo electrónico.

P.ej.Quiero buscar "@gmail.com" para encontrar todos los correos electrónicos enviados a una dirección de Gmail.

La ejecución de una consulta de Lucene para "*@gmail.com" genera un error; los asteriscos no pueden estar al inicio de las consultas.Al ejecutar una consulta para "@gmail.com" no se obtienen coincidencias, porque "foo@gmail.com" se considera una palabra completa y no se pueden buscar solo partes de una palabra.

¿Cómo puedo hacer esto?

¿Fue útil?

Solución

Nadie dio una respuesta satisfactoria, por lo que comenzamos a buscar en la documentación de Lucene y descubrimos que podemos lograr esto utilizando analizadores y tokenizadores personalizados.

La respuesta es esta:cree un WhitespaceAndAtSymbolTokenizer y un WhitespaceAndAtSymbolAnalyzer, luego vuelva a crear su índice usando este analizador.Una vez que hagas esto, una búsqueda de "@gmail.com" arrojará todas las direcciones de Gmail, porque se ve como una palabra separada gracias al Tokenizer que acabamos de crear.

Aquí está el código fuente, en realidad es muy simple:

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

¡Eso es todo!Ahora sólo necesita reconstruir su índice y realizar todas las búsquedas utilizando este nuevo Analizador.Por ejemplo, para escribir documentos en su índice:

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

Al realizar búsquedas también se debe utilizar el analizador:

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

Otros consejos

Veo que tienes tu solución, pero la mía habría evitado esto y habría agregado un campo a los documentos que estás indexando llamado email_domain, en el que habría agregado el dominio analizado de la dirección de correo electrónico.Puede parecer una tontería, pero la cantidad de almacenamiento asociada con esto es bastante mínima.Si le apetece ser más sofisticado, digamos que algún dominio tiene muchos subdominios, en su lugar podría crear un campo en el que vaya el dominio invertido, de modo que almacenaría com.gmail, com.company.department o ae.eim para poder encontrar todas las direcciones relacionadas con los Emiratos Árabes Unidos con una consulta de prefijo 'ae'.

También hay setAllowLeadingComodín

Pero tenga cuidadoso.Esto podría resultar muy caro en términos de rendimiento (es por eso que está deshabilitado de forma predeterminada).Quizás en algunos casos esto sería una solución fácil, pero preferiría un Tokenizer personalizado como lo indica Judá Himango, también.

Podrías invertir un campo separado que indexe la dirección de correo electrónico:Index 'foo@gmail.com' como 'moc.liamg@of' que le permite hacer una consulta para "moc.liamg@*"

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top