2011-04-01 20 views
15

Acabo de aventurarme en el mundo aparentemente simple pero extremadamente complejo de la búsqueda. Para una aplicación, debo crear un mecanismo de búsqueda para buscar usuarios por sus nombres.Búsqueda de nombres con Apache Solr

Después de leer numerosos mensajes y artículos que incluyen:

How can I use Lucene for personal name (first name, last name) search?
http://dublincore.org/documents/1998/02/03/name-representation/
what's the best way to search a social network by prioritizing a users relationships first?
http://www.gossamer-threads.com/lists/lucene/java-user/120417
Lucene Index and Query Design Question - Searching People
Lucene Fuzzy Search for customer names and partial address

... y algunos otros que no puedo encontrar en-el- momento. Y conseguir por lo menos-indexación y búsqueda básica de trabajo en mi máquina he ideado el siguiente esquema para el usuario a buscar:

1) Tener un primer, segundo y tercer campo del nombre y el índice de aquellos con Solr
2) Utilizar edismax como la requestParser de varias columnas en busca
3) Use una combinación de filtros de normalización, tales como: transliteración, convesrion latino-a-ASCII, etc.
4) utilizar Finalmente búsqueda difusa

Evidentemente, al ser muy nuevo en esto No estoy seguro si lo anterior es la mejor manera de hacerlo y me gustaría saber de usuarios experimentados que tienen una mejor idea que yo en este campo.

I necesita ser capaz de coincidir con los nombres de las siguientes maneras:

1) plegable Accent: Jorn coincide Jörn y viceversa
2) ortografías alternativas: Karl coincide Carl y viceversa
3) acortado representaciones (creo que hago esto con el SynonymFilterFactory): Sue coincide con Susanne, etc.
4) Levenstein juego: Jonn coincide con Juan, etc.
5) Soundex juego: Elin y Ellen

Cualquier orientación, las críticas o co Los mimos son bienvenidos. Por favor, avíseme si esto es posible ... o tal vez solo estoy soñando despierto. :)


EDITAR

también debo añadir que yo también tengo un campo de nombre completo en caso de que algunas personas tienen nombres largos, como un ejemplo de uno de los postes: Jon Paul o del Carmen debe también coincide con Jon Paul Del Carmen

Y dado que este es un proyecto nuevo, puedo modificar el esquema y la arquitectura de la forma que considero adecuada, por lo que existen restricciones muy limitadas.

+1

Usted obtendrá los mejores resultados al tratar de resolver 1 tema a la vez. (Probablemente lo sepas, solo te estoy recordando ;-)) ... Y trataría de resolver primero los problemas más fáciles. Su lista parece ordenarse en orden inverso de dificultad. Empezaría con el n. ° 5 y volvería al n. ° 1. Cada uno de estos temas puntúa una pregunta separada aquí en S.O. Finalmente, creo que obtendrás una mejor ayuda en los foros de usuarios en el sitio principal de cada proyecto. Pasé varias horas hace unos meses leyendo el foro de lucene en apache.org y me pareció muy alentador e iluminador. ¡Buena suerte! – shellter

+0

Doblar acento, hasta donde yo sé, realmente no sé sueco, por ejemplo, pero cuando se usa un determinado analizador de lenguaje en el texto, siempre que se use ese mismo analizador en la consulta, se indexará documento de búsqueda. Aunque no sé mucho acerca de la detección del lenguaje en un texto. – Joyce

Respuesta

9

Parece que está atendiendo un corpus con búsquedas que necesita coincidir muy poco?

Si lo hace, querrá elegir sus campos y establecer diferentes impulsos para clasificar los resultados.

Así tener campos separados "copiados" en Solr:

  • un campo de nombre completo exacto (con filtros)
  • campo multivalor con filtros ASCIIFolding, Minúsculas ...
  • campo multivalor con el ASCIIFolding SynonymFilterFactory, minúsculas ...
  • PhoneticFilterFactory (con Caverphone o Double-Metaphone)

See Also: more non-english Soundex discussion

Sinónimos para nombres, no sé si hay un sinónimo público disponible.

Búsqueda difusa, no la he encontrado útil, utiliza la distancia de Levenshtein.

Otros filtros e indexación obtienen resultados superiores de "búsqueda relevante".

caracteres Unicode en nombres se pueden manejar con el ASCIIFoldingFilterFactory

Usted está describiendo soluciones en la delantera de casos de uso previstos.

Si quieres resultados de calidad, el plan de ajuste de su Search Relevance

Esta afinación será especialmente valiosa, al intentar coincidir en sinónimos, como MacDonald y McDonald (que tiene una distancia de Levenshtein más grande que Carl y Karl).

+0

Gracias por su respuesta. Como tenía prisa por implementar esta función, eliminé algunas características y las implementé de la siguiente manera (en general es similar a su sugerencia): 1) Agregó un campo con nombre completo (como dijo) 2) Creó un analizador con minúsculas, ASCIIFolding y analizador de n-gramas (para sugerir automáticamente) 3) Agregué un SynonymFilter También utilicé el analizador de consultas edismax. Dado que su solución estuvo cerca de mi intento; Marcaré esta respuesta como correcta. :) ¡Gracias de nuevo por su tiempo! – shachibista

0

Creamos un tipo de campo 'nombre' simple que permite mezclar las partes 'clave' (por ejemplo, SOUNDEX) y 'por parejas' de las respuestas anteriores.

Aquí está la descripción general:

  1. en tiempo de índice, campos del tipo de encargo son indexados en un conjunto de (sub) campos con valores respectivos utilizados para la alta recuperación emparejan diferentes tipos de variaciones

Aquí está el núcleo de su aplicación ...

List<IndexableField> createFields(SchemaField field, String name) { 
     Collection<FieldSpec> nameFields = deriveFieldsForName(name); 
     List<IndexableField> docFields = new ArrayList<>(); 
     for (FieldSpec fs : nameFields) { 
      docFields.add(new Field(fs.getName(), fs.getStringValue(), 
         fs.getLuceneField())); 
     } 
     docFields.add(createDocValues(field.getName(), new Name(name))); 
     return docFields; 
} 

el corazón de este es deriveFieldsForName (nombre) en el que se puede incluir f 'claves' PhoneticFilters rom, LowerCaseFolding, etc.

  1. en tiempo de consulta, primero una consulta personalizada Lucene es producido que ha sido sintonizado para una recuperación y que utiliza los mismos campos que el tiempo índice

Aquí está el núcleo de su implementación ...

public Query getFieldQuery(QParser parser, SchemaField field, String val) { 
     Name name = parseNameString(externalVal, parser.getParams()); 
     QuerySpec querySpec = buildQuery(name); 
     return querySpec.accept(new SolrQueryVisitor(field.getName())); 
} 

El corazón de este método es el BuildQuery (nombre) que debe producir una consulta que es consciente de deriveFieldsForName (nombre) por encima de lo que para un nombre de consulta dado que encontrará buenos nombres de los candidatos.

  1. luego la segunda, característica Rerank del Solr se usa para aplicar un algoritmo de re-puntuación alta precisión para reordenar los resultados

es lo que este se ve como en la consulta aquí. ..

&rq={!myRerank reRankQuery=$rrq} &rrq={!func}myMatch(fieldName, "John Doe") 

El contenido de myMatch podría tener una implementación por pares de Levenstein o Jaro-Winkler.

N. B. Nuestra implementación completa utiliza código propietario para deriveFieldsForName, buildQuery y myMatch (consulte http://www.basistech.com/text-analytics/rosette/name-indexer/) para manejar más tipos de variaciones que las mencionadas anteriormente (por ejemplo, espacios faltantes, idiomas cruzados).

+0

Esta publicación no vale mucho (excepto para publicitar su producto comercial), sin explicar la función deriveFieldsForName(). La siguiente imagen ofrece algunos consejos: http://www.basistech.com/wp-content/uploads/2013/12/name-matching-capabilities.png –

+0

Entendido. Extendí la respuesta para tratar de aclarar cómo aplicarla sin necesidad del producto comercial. – dmurga

1

La respuesta en otro post es bastante bueno: Training solr to recognize nicknames or name variants

<fieldType name="name_en" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true"> 
    <analyzer type="index"> 
    <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/> 
    <filter class="solr.LowerCaseFilterFactory"/> 
    <filter class="solr.ASCIIFoldingFilterFactory"/> 
    </analyzer> 
    <analyzer type="query"> 
    <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
    <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/> 
    <filter class="solr.LowerCaseFilterFactory"/> 
    <filter class="solr.ASCIIFoldingFilterFactory"/> 
    <filter class="solr.SynonymFilterFactory" synonyms="english_names.txt" ignoreCase="true" expand="true"/> 
    </analyzer> 
</fieldType> 
0

para Buscar por nombre fonético también se podría tratar el Beider-Morse Filter que funciona bastante bien si usted tiene una mezcla de nombres de diferentes países .

Si desea utilizarlo con una función de escritura anticipada, combinarlo con un EdgeNGramFilter:

<fieldType name="phoneticNames" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true"> 
    <analyzer type="index"> 
    <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
    <filter class="solr.BeiderMorseFilterFactory" nameType="GENERIC" ruleType="APPROX" concat="true" languageSet="auto"/> 
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="3" maxGramSize="15"/> 
    </analyzer> 
    <analyzer type="query"> 
    <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
    <filter class="solr.BeiderMorseFilterFactory" nameType="GENERIC" ruleType="APPROX" concat="true" languageSet="auto"/> 
    </analyzer> 
</fieldType> 
Cuestiones relacionadas