2011-05-24 59 views
7

我想在索引中查找特殊字符。如何搜索特殊字符(+ !?)在Lucene的

我逃過查詢字符串的所有特殊字符,但是當我爲+上的Lucene索引進行查詢它創建查詢爲+()。

因此,它在搜索領域沒有。

如何解決這個問題?我的索引包含這些特殊字符。

+0

請舉例說明您正在搜索的內容以及創建的內容。 「查詢爲+」是什麼意思? – morja 2011-05-24 08:53:39

+0

我正在尋找特殊字符,如+! ?等等,我得到了解決方案。實際上,我們正在使用一些自定義分析器,並且由於應用了過濾器,因此給出了blanck查詢(+())。但是當我使用KeywordAnalyzer它工作。 **任何輸入如何?** – user660024 2011-05-24 09:47:49

+0

您是否使用相同的分析器進行索引和查詢?請在調用搜索之前添加描述確切查詢的代碼示例以及如何處理它。 – 2011-05-24 12:35:44

回答

10

如果您使用的是StandardAnalyzer,將放棄非alphanum字符。嘗試使用WhitespaceAnalyzer將相同的值編入索引並查看是否保留了所需的字符。它可能還會保留你不想要的東西:那時候你可能會考慮編寫自己的分析器,這基本上意味着創建一個TokenStream堆棧來完成你需要的處理。

例如,SimpleAnalyzer實現以下管道:

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

剛剛較低情況下,令牌。

StandardAnalyzer做得更多:

/** 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; 
} 

您可以org.apache.lucene.analysis從這些和其他成分混合&匹配,或者你可以寫自己的專業TokenStream情況下,由您的自定義Analyzer裹成一個處理管道。其他

有一點要看看是你用什麼樣的CharTokenizerCharTokenizer是一個抽象類,它指定用於標記文本字符串的機器。它被一些更簡單的分析儀使用(但不是StandardAnalyzer)。 Lucene有兩個子類:LetterTokenizerWhitespaceTokenizer。您可以通過創建自己的方法來保留所需的字符,並通過實施boolean isTokenChar(char c)方法來打破不需要的字符。

1

也許這不是實際的作者,而是可以搜索特殊字符,你需要:

  1. 創建自定義分析
  2. 將其用於索引和搜索

例如,它是如何工作的對我來說:

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

    } 
} 
}