2017-04-06 38 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