Pregunta

El uso de Hibernate búsqueda Anotaciones (en su mayoría sólo @Field(index = Index.TOKENIZED)) he indexado una serie de campos relacionados con una clase PERSISTED mía llamada Compuesto. Me he configuración de búsqueda de texto sobre todos los campos indexados, utilizando el MultiFieldQueryParser , que hasta ahora ha funcionado bien.

Entre los campos indexados y de búsqueda es un campo llamado CompoundName, con valores de ejemplo:

  • 3-Hydroxyflavone
  • 6,4'-Dihydroxyflavone

Cuando busco cualquiera de estos valores en su totalidad se devuelven las instancias compuesto relacionado. Sin embargo los problemas se producen cuando se utiliza el nombre parcial y presento comodines:

  • búsqueda de 3-Hydroxyflav* todavía da el golpe correcto, pero
  • búsqueda de 6,4'-Dihydroxyflav* no encuentra nada.

Ahora como estoy bastante nuevo en Lucene / Hibernate-búsqueda, no estoy muy seguro de dónde buscar en este punto .. Creo que podría tener algo que ver con la ' presente en la segunda consulta, pero no saben cómo proceder .. debo buscar en Tokenizers / Analizadores / QueryParsers o algo completamente distinto?

O puede alguien decirme cómo puedo conseguir la segunda búsqueda con patrones para que coincida, preferiblemente sin romper el comportamiento multicampo-búsqueda?

Estoy usando Hibernate-Búsqueda 3.1.0.GA y Lucene núcleos 2.9.3.


Algunos bits de código pertinentes para ilustrar mi enfoque actual:

Las partes pertinentes de la clase Compuesto indexada:

@Entity
@Indexed
@Data
@EqualsAndHashCode(callSuper = false, of = { "inchikey" })
public class Compound extends DomainObject {
    @NaturalId
    @NotEmpty
    @Length(max = 30)
    @Field(index = Index.TOKENIZED)
    private String                  inchikey;

    @ManyToOne
    @IndexedEmbedded
    private ChemicalClass           chemicalClass;

    @Field(index = Index.TOKENIZED)
    private String                  commonName;
...
}

¿Cómo busco actualmente en los campos indexados:

String[] searchfields = Compound.getSearchfields();
MultiFieldQueryParser parser = 
    new MultiFieldQueryParser(Version.LUCENE_29, searchfields, new StandardAnalyzer(Version.LUCENE_29));
FullTextSession fullTextSession = Search.getFullTextSession(getSession());
FullTextQuery fullTextQuery = 
    fullTextSession.createFullTextQuery(parser.parse("searchterms"), Compound.class);
List<Compound> hits = fullTextQuery.list();
¿Fue útil?

Solución

Creo que su problema es una combinación de problemas del analizador y del lenguaje de consulta. Es difícil decir exactamente lo que causa el problema. Para averiguar esto le recomiendo que usted examina el índice con la función de índice Lucene Lucas .

Dado que en la configuración de Hibernate búsqueda no está usando un analizador de encargo del defecto - StandardAnalyzer - se utiliza. Esto sería consistente con el hecho de que utiliza StandardAnalyzer en el constructor de MultiFieldQueryParser (utilizar siempre el mismo analizador para la indexación y búsqueda!). Lo que no estoy tan seguro de cómo es "6,4'-dihidroxiflavona" se tokenized por StandardAnalyzer . Que lo primero que tiene que descubrir. Por ejemplo, el javadoc dice:

Divisiones palabras al guiones, a menos hay un número en el modo, en cuyo caso todo el token es interpretado como un número de producto y está no dividida.

Puede ser que usted necesita para escribir su propio analizador, que tokenizes sus nombres químicos de la manera que lo necesite para sus casos de uso.

A continuación, el analizador de consultas. Asegúrese de entender la sintaxis de consulta - Lucene consulta sintaxis . Algunos caracteres tienen un significado especial, por ejemplo, un '-'. Podría ser que su consulta se analiza la manera incorrecta.

De cualquier manera, en primer lugar os paso para descubrir cómo sus nombres químicos consiguen tokenized. Espero que ayude.

Otros consejos

Uso WhitespaceAnalyzer en lugar de StandardAnalyzer. Se acaba de dividir a los espacios en blanco, y no en las comas, guiones, etc. (que no minúsculas ellos, sin embargo, por lo que tendrá que construir su propia cadena de espacios en blanco + minúsculas, suponiendo que usted quiere que su búsqueda distinga entre mayúsculas y minúsculas). Si usted tiene que hacer las cosas de forma diferente para diferentes campos, se puede utilizar un PerFieldAnalyzer.

Puede no sólo configurarlo para que ONU-tokens, porque eso va a interpretar todo el cuerpo del texto como una ficha.

escribí mi propio analizador:

import java.util.Set;
import java.util.regex.Pattern;

import org.apache.lucene.index.memory.PatternAnalyzer;
import org.apache.lucene.util.Version;

public class ChemicalNameAnalyzer extends PatternAnalyzer {

    private static Version version = Version.LUCENE_29;
    private static Pattern pattern = compilePattern();
    private static boolean toLowerCase = true;
    private static Set stopWords = null;

    public ChemicalNameAnalyzer(){
        super(version, pattern, toLowerCase, stopWords);
    }

    public static Pattern compilePattern() {
        StringBuilder sb =  new StringBuilder();
        sb.append("(-{0,1}\\(-{0,1})");//Matches an optional dash followed by an opening round bracket followed by an optional dash  
        sb.append("|");//"OR" (regex alternation)
        sb.append("(-{0,1}\\)-{0,1})"); 
        sb.append("|");//"OR" (regex alternation)
        sb.append("((?<=([a-zA-Z]{2,}))-(?=([^a-zA-Z])))");//Matches a dash ("-") preceded by two or more letters and succeeded by a non-letter
        return Pattern.compile(sb.toString());
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top