【问题标题】:Applying the same Analyzer to Queries and Fields将相同的分析器应用于查询和字段
【发布时间】:2020-01-21 19:55:46
【问题描述】:

我正在尝试为我的 API 后端构建基本搜索。用户传递任意查询,后端应该返回结果(显然)。我更喜欢与本地索引以及 Elasticsearch 一起使用的解决方案。

在我的实体上,我定义了一个这样的分析器:

@AnalyzerDef(name = "ngram",
    tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class ),
    filters = {
      @TokenFilterDef(factory = StandardFilterFactory.class),
      @TokenFilterDef(factory = LowerCaseFilterFactory.class),
      @TokenFilterDef(factory = StopFilterFactory.class),
      @TokenFilterDef(factory = NGramFilterFactory.class,
        params = {
          @Parameter(name = "minGramSize", value = "2"),
          @Parameter(name = "maxGramSize", value = "3") } )
    }
)

对于查询,我尝试了以下方法:

    FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(this.entityManager);
    Analyzer analyzer = fullTextEntityManager.getSearchFactory().getAnalyzer("ngram");

    QueryParser queryParser = new MultiFieldQueryParser(ALL_FIELDS, analyzer);
    queryParser.setDefaultOperator(QueryParser.AND_OPERATOR);
    org.apache.lucene.search.Query query = queryParser.parse(queryString);


    javax.persistence.Query persistenceQuery = 
            fullTextEntityManager.createFullTextQuery(query, MyEntity.class);

    List<MyEntity> result = persistenceQuery.getResultList();

据我了解,我需要为查询提供分析器,以便搜索查询是“ngram-tokenized”并且可以找到匹配项。之前,我使用了 SimpleAnalyzer,结果,搜索只匹配了完整的单词——我认为——支持我的理论(对不起,我还在学习这个)。

上面的代码给了我一个 NullPointerException:

java.lang.NullPointerException: null
        at org.hibernate.search.engine.impl.ImmutableSearchFactory.getAnalyzer(ImmutableSearchFactory.java:370) ~[hibernate-search-engine-5.11.1.Final.jar:5.11.1.Final]
        at org.hibernate.search.engine.impl.MutableSearchFactory.getAnalyzer(MutableSearchFactory.java:203) ~[hibernate-search-engine-5.11.1.Final.jar:5.11.1.Final]
        at org.hibernate.search.impl.SearchFactoryImpl.getAnalyzer(SearchFactoryImpl.java:50) ~[hibernate-search-orm-5.11.1.Final.jar:5.11.1.Final]

在行中

Analyzer analyzer = fullTextEntityManager.getSearchFactory().getAnalyzer("ngram");

【问题讨论】:

    标签: hibernate-search


    【解决方案1】:

    使用 Elasticsearch 集成时,您无法从 Hibernate Search 中检索分析器,因为在这种情况下,本地没有分析器:分析器仅存在于 Elasticsearch 集群中的远程。

    如果您只需要查询语法的一个子集,请尝试"simple query string" query:它是一个可以使用 DSL 构建的查询(因此它与 Lucene 和 Elasticsearch 相同)并且提供了最常见的功能(布尔查询,模糊性,短语,...)。例如:

    Query luceneQuery = queryBuilder.simpleQueryString()
        .onFields("name", "history", "description")
        .matching("war + (peace | harmony)")
        .createQuery();
    

    语法有点不同,但这只是因为它针对最终用户并试图变得更简单。

    编辑:如果不能选择简单的查询字符串,您可以手动创建分析器:即使使用 Elasticsearch 集成,这也应该可以工作。 org.apache.lucene.analysis.custom.CustomAnalyzer#builder() 应该是一个很好的起点。该类的 javadoc 中有几个示例。 确保您只创建一次分析器并将其存储在某个地方,例如在静态常量中:创建分析器可能成本很高。

    【讨论】:

    • 我想我之前在你的其他帖子/答案中看到过这个建议。我不这样做的原因是我需要能够单独查询字段,例如"name 包含 Foo,tags 包含 bar,somefield 完全匹配 bla"
    • 是的。我添加了一段关于此的内容。
    • 太棒了!
    猜你喜欢
    • 1970-01-01
    • 2019-10-03
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    • 2020-11-19
    • 2011-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多