2011-05-24 28 views
7

Quiero buscar caracteres especiales en el índice.Cómo buscar caracteres especiales (+! ?:) En Lucene

He escapado de todos los caracteres especiales en la cadena de consulta, pero cuando realizo la consulta como + en lucene en el índice crea la consulta como +().

Por lo tanto, no busca en ningún campo.

¿Cómo solucionar este problema? Mi índice contiene estos caracteres especiales.

+0

Por favor, den un ejemplo de lo que está buscando y de lo que se crea. ¿Qué quiere decir con "query as +"? – morja

+0

Estoy buscando caracteres especiales como +! ? etc. Bueno, tengo la solución. En realidad, estamos usando un analizador personalizado y debido a los filtros aplicados, nos estaba dando una consulta blanck (+()). Pero cuando utilicé KeywordAnalyzer funcionó. ** ¿Alguna información sobre cómo se ingresa? ** – user660024

+0

¿Está utilizando el mismo analizador para la indexación y la consulta? Agregue un ejemplo de código que describa su consulta exacta y cómo la procesa antes de llamar a la búsqueda. –

Respuesta

10

Si está utilizando StandardAnalyzer, descartará caracteres que no sean alfanuméricos. Intente indexar el mismo valor con un WhitespaceAnalyzer y vea si eso conserva los caracteres que necesita. También podría mantener cosas que no desea: ahí es cuando podría considerar escribir su propio Analizador, lo que básicamente significa crear una pila TokenStream que haga exactamente el tipo de procesamiento que necesita.

Por ejemplo, el SimpleAnalyzer implementa las siguientes tuberías:

@Override 
public TokenStream tokenStream(String fieldName, Reader reader) { 
    return new LowerCaseTokenizer(reader); 
} 

cuales sólo menores-casos los tokens.

El StandardAnalyzer hace mucho más:

/** Constructs a {@link StandardTokenizer} filtered by a {@link 
StandardFilter}, a {@link LowerCaseFilter} and a {@link StopFilter}. */ 
@Override 
public TokenStream tokenStream(String fieldName, Reader reader) { 
    StandardTokenizer tokenStream = new StandardTokenizer(matchVersion, reader); 
    tokenStream.setMaxTokenLength(maxTokenLength); 
    TokenStream result = new StandardFilter(tokenStream); 
    result = new LowerCaseFilter(result); 
    result = new StopFilter(enableStopPositionIncrements, result, stopSet); 
    return result; 
} 

Usted puede mezclar & partido de estos y otros componentes en org.apache.lucene.analysis, o puede escribir sus propios TokenStream instancias especializadas que se envuelven en una canalización de procesamiento por su aduana Analyzer .

Otra cosa a mirar es qué tipo de CharTokenizer estás usando. CharTokenizer es una clase abstracta que especifica la maquinaria para tokenizar cadenas de texto. Es utilizado por algunos Analizadores más simples (pero no por el StandardAnalyzer). Lucene viene con dos subclases: un LetterTokenizer y un WhitespaceTokenizer. Puede crear el suyo propio que conserve los caracteres que necesita y rompe aquellos que no implementa el método boolean isTokenChar(char c).

1

tal vez no es real para el autor, sino que sea capaz de buscar caracteres especiales que necesita:

  1. Crear analizador de encargo
  2. Lo utilizan para indexar y buscar

Ejemplo de cómo funciona para mí:

import org.apache.lucene.analysis.Analyzer; 
import org.apache.lucene.analysis.custom.CustomAnalyzer; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 
import org.apache.lucene.document.TextField; 
import org.apache.lucene.index.DirectoryReader; 
import org.apache.lucene.index.IndexReader; 
import org.apache.lucene.index.IndexWriter; 
import org.apache.lucene.index.IndexWriterConfig; 
import org.apache.lucene.queryparser.classic.QueryParser; 
import org.apache.lucene.search.*; 
import org.apache.lucene.store.RAMDirectory; 
import org.junit.Test; 

import java.io.IOException; 

import static org.hamcrest.Matchers.equalTo; 
import static org.junit.Assert.assertThat; 

public class LuceneSpecialCharactersSearchTest { 

/** 
* Test that tries to search a string by some substring with each special character separately. 
*/ 
@Test 
public void testSpecialCharacterSearch() throws Exception { 
    // GIVEN 
    LuceneSpecialCharactersSearch service = new LuceneSpecialCharactersSearch(); 
    String[] luceneSpecialCharacters = new String[]{"+", "-", "&&", "||", "!", "(", ")", "{", "}", "[", "]", "^", "\"", "~", "*", "?", ":", "\\"}; 

    // WHEN 
    for (String specialCharacter : luceneSpecialCharacters) { 
     String actual = service.search("list's special-characters " + specialCharacter); 

     // THEN 
     assertThat(actual, equalTo(LuceneSpecialCharactersSearch.TEXT_WITH_SPECIAL_CHARACTERS)); 
    } 
} 

private static class LuceneSpecialCharactersSearch { 
    private static final String TEXT_WITH_SPECIAL_CHARACTERS = "This is the list's of special-characters + - && || ! () { } [ ]^\" ~ ? : \\ *"; 

    private final IndexWriter writer; 

    public LuceneSpecialCharactersSearch() throws Exception { 
     Document document = new Document(); 
     document.add(new TextField("body", TEXT_WITH_SPECIAL_CHARACTERS, Field.Store.YES)); 

     RAMDirectory directory = new RAMDirectory(); 
     writer = new IndexWriter(directory, new IndexWriterConfig(buildAnalyzer())); 
     writer.addDocument(document); 
     writer.commit(); 
    } 

    public String search(String queryString) throws Exception { 
     try (IndexReader reader = DirectoryReader.open(writer, false)) { 
      IndexSearcher searcher = new IndexSearcher(reader); 

      String escapedQueryString = QueryParser.escape(queryString).toLowerCase(); 

      Analyzer analyzer = buildAnalyzer(); 
      QueryParser bodyQueryParser = new QueryParser("body", analyzer); 
      bodyQueryParser.setDefaultOperator(QueryParser.Operator.AND); 


      Query bodyQuery = bodyQueryParser.parse(escapedQueryString); 
      BooleanQuery query = new BooleanQuery.Builder() 
        .add(new BooleanClause(bodyQuery, BooleanClause.Occur.SHOULD)) 
        .build(); 
      TopDocs searchResult = searcher.search(query, 1); 

      return searcher.doc(searchResult.scoreDocs[0].doc).getField("body").stringValue(); 
     } 
    } 

    /** 
    * Builds analyzer that is used for indexing and searching. 
    */ 
    private static Analyzer buildAnalyzer() throws IOException { 
     return CustomAnalyzer.builder() 
       .withTokenizer("whitespace") 
       .addTokenFilter("lowercase") 
       .addTokenFilter("standard") 
       .build(); 

    } 
} 
}