2017-04-06 71 views
0

我想以一種與FieldBridges和手動搜索相配的方式實現lucene分析器。理想情況下,我希望儘可能少的代碼重複。使用FieldBridges實現Lucene分析器

我知道大多數教程都告訴你用@AnalyzerDef註解來初始化你的分析器,而當我做到了這一點,並且讓所有的工作都成功的時候,我無法使FieldBridges中創建的字段能夠尊重分析器。 (使用luceneoptions.addFieldToDocument創建)。

我試圖找到另一種方式做到這一點,但文件是稀疏的。

這就是我想出了(保持這個職位短一些代碼的緣故經過編輯,但我將發佈更多,如果要求。)

創建分析:

public static org.apache.lucene.analysis.Analyzer getEnglishWordAnalyser() { 
     org.apache.lucene.analysis.Analyzer analyser = null; 

     try { 
      analyser = CustomAnalyzer.builder() 
        .addCharFilter(HTMLStripCharFilterFactory.class) 
        .addCharFilter(MappingCharFilterFactory.class, getMappingSettings()) 
        .withTokenizer(StandardTokenizerFactory.class) 
        .addTokenFilter(StandardFilterFactory.class) 
        .addTokenFilter(LowerCaseFilterFactory.class) 
        .addTokenFilter(SnowballPorterFilterFactory.class, getSnowballPorterSettings()) 
        .addTokenFilter(SynonymFilterFactory.class, getSynonymSettings()) 
        .addTokenFilter(ASCIIFoldingFilterFactory.class) 
        .addTokenFilter(PhoneticFilterFactory.class, getPhoneticSettings()) 
        .addTokenFilter(StopFilterFactory.class, getStopSettings()) 
        .build(); 

     } catch (IOException ex) { 
      logger.info("[SearchConfig] [englishWordAnalyser] Failed to create components", ex); 
     } 

     return analyser; 
    } 

創建場分析:

protected StringField createStringField(String name, String value, LuceneOptions luceneOptions) { 
     final StringField field = new StringField(name, value, luceneOptions.getStore()); 

     final Analyzer analyzer = SearchConfig.getEnglishWordAnalyser(); 

     try { 
      final TokenStream tokenStream = analyzer.tokenStream(name, new StringReader(value)); 
      tokenStream.reset(); 

      field.setBoost(luceneOptions.getBoost()); 
      field.setTokenStream(tokenStream); 
      field.setStringValue(value); 

      tokenStream.end(); 
      tokenStream.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     analyzer.close(); 
     return field; 
    } 

從FieldBridge添加一個新的領域:

createStringField("NAME", "VALUE", luceneOptions); 

我也希望能夠創造一個MultiFieldQueryParser這樣當使用這種分析儀:

final QueryParser parser = new MultiFieldQueryParser(getClassLuceneFields(clazz), getEnglishWordAnalyser()); 

現在我測試的分析與MultiFieldQueryParser,它似乎工作得很好,但是當FieldBridges是被索引它伸出與此錯誤:

java.lang.IllegalArgumentException: TokenStream fields must be indexed and tokenized 

這是在setTokenStream上的createStringField中引起的。

有沒有人有任何想法?

我可能完全走錯了方向,如果是這樣,有沒有人有任何替代方案也適合我的用例。

乾杯

回答

1

我很擔心這不是Lucene的工作原理。 Lucene希望您在其字段中構建具有未分析值的文檔,並且在將文檔放入索引時將負責分析文檔。

Hibernate Search負責設置正確的配置,以便Lucene知道每個字段使用哪個分析器。碰巧,這很容易配置爲標準@Field字段(@Field(analyzer = ...)),但不適用於在現場橋樑中添加的字段。

目前,最簡單的解決方案將是第in this blog post號分析器鑑別器。這不是分析儀鑑別器的預期目的,但它會起作用。

基本上你將有:

  • 定義使用@AnalyzerDef像往常一樣
  • 產生一個分析儀鑑別你的域映射到相應的分析定義分析:

    public class MyDiscriminator implements Discriminator { 
        public String getAnalyzerDefinitionName(Object value, Object entity, String fieldName) { 
         switch (fieldName) { 
         case "foo": 
          return "analyzerNameForFieldFoo"; 
         case "bar": 
          return "analyzerNameForFieldBar"; 
         default: 
          return null; // Use the default analyzer 
         } 
        } 
    } 
    
  • 應用鑑別器到您的實體:

    @Indexed 
    @Entity 
    @AnalyzerDiscriminator(impl = MyDiscriminator.class) 
    public class MyEntity { 
        // ... 
    } 
    

請參閱here瞭解關於分析儀鑑別器的更多文檔。

+0

Thankyou Yoann,它的工作原理 – Headchopperz