使用简单查询字符串时,空白令牌生成器不起作用

时间:2019-04-10 05:58:53

标签: hibernate-search

我首先使用SimpleQueryString实现查询搜索,如下所示。

实体定义

@Entity
@Indexed
@AnalyzerDef(name = "whitespace", tokenizer = @TokenizerDef(factory = WhitespaceTokenizerFactory.class),
    filters = {
        @TokenFilterDef(factory = LowerCaseFilterFactory.class),
        @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class)
    })

public class AdAccount implements SearchableEntity, Serializable {

    @Id
    @DocumentId
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Field(store = Store.YES, analyzer = @Analyzer(definition = "whitespace"))
    @Column(name = "NAME")
    private String name;

    //other properties and getters/setters
}

我在这里使用空白标记器工厂,因为默认的标准分析器会忽略特殊字符,这在我的用例中并不理想。我引用的文档是https://lucene.apache.org/solr/guide/6_6/tokenizers.html#Tokenizers-WhiteSpaceTokenizer。在此文档中,它指出了简单令牌生成器,该符号生成器在空白处拆分文本流并返回非空白字符序列作为令牌。

SimpleQueryString方法

protected Query inputFilterBuilder() {
    SimpleQueryStringMatchingContext simpleQueryStringMatchingContext = queryBuilder.simpleQueryString().onField("name");

    return simpleQueryStringMatchingContext
        .withAndAsDefaultOperator()
        .matching(searchRequest.getQuery() + "*").createQuery();
}

searchRequest.getQuery()返回搜索查询字符串,然后在结尾处附加前缀运算符,以便它支持前缀查询。

但是,以下示例无法正常运行。 假设我有一个名称为“ AT&T帐户”的实体,当使用“ AT&”进行搜索时,它不会返回该实体。

然后我进行了以下更改,以直接使用空白分析器。这次使用“ AT&”进行搜索符合预期。但是搜索现在区分大小写,即使用“ at&”进行搜索现在不返回任何内容。

@Field
@Analyzer(impl = WhitespaceAnalyzer.class)
@Column(name = "NAME")
private String name;

我的问题是:

  1. 为什么在我第一次尝试使用空白工厂时它不起作用?我假设使用工厂与使用实际的分析器实现有所不同吗?

  2. 如果在第二次尝试中使用@Analyzer注释,如何使搜索不区分大小写?

1 个答案:

答案 0 :(得分:0)

  

为什么在我第一次尝试使用空白工厂时它不起作用?我假设使用工厂与使用实际的分析器实现有所不同吗?

通配符和前缀查询(在查询字符串中添加后缀*后使用的查询)永远不会应用分析。这意味着您的小写过滤器未应用于搜索查询,但已应用于索引文本,这意味着它将永远不匹配:AT&*与索引的at&t不匹配。

仅使用@Analyzer注释是因为您在索引时已删除了小写字母。使用此分析器,您最终在索引中使用AT&T(大写),并且AT&* 确实与索引的AT&T相匹配。不过,这只是偶然的:如果您为At&t编制索引,您最终将在索引中以At&t结束,并且将遇到相同的问题。

  

如果在第二次尝试中使用@Analyzer批注,如何使搜索不区分大小写?

如上所述,@Analyzer注释不是解决方案,实际上使搜索变得更糟。

没有内置的解决方案可以使通配符和前缀查询应用分析,这主要是因为分析可以删除诸如?*之类的模式字符,并且效果不佳。

您可以还原您的初始分析器,并自行将查询转换为小写字母,但这只能解决问题:ascii折叠和其他分析功能将不起作用。

我通常建议的解决方案是使用edge-ngrams过滤器。这个想法是为每个单词的每个前缀建立索引,因此即使没有通配符,“ AT&T帐户”也将以术语a, at, at&, at&t, a, ac, acc, acco, accou, accoun, account进行索引,而搜索“ at&”将返回正确的结果。

有关更广泛的说明,请参见this answer

如果使用ELasticsearch集成,则将不得不依靠黑客使“仅查询”分析器正常工作。参见here