我首先使用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
}
我在这里使用了white space tokenizer工厂,因为默认的标准分析器会忽略特殊字符,这在我的用例中并不理想。我提到的文件是https://lucene.apache.org/solr/guide/6_6/tokenizers.html#Tokenizers-WhiteSpaceTokenizer。在本文档中,它指出Simple tokenizer将文本流拆分为空白并将非空白字符序列作为标记返回。
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;
我的问题是:
当我第一次尝试使用白色空间工厂时,为什么它不起作用?我假设使用工厂与使用实际的分析仪实现不同?
通配符和前缀查询(在查询字符串中添加*
后缀时使用的查询)不会应用分析。这意味着您的小写过滤器不会应用于您的搜索查询,但它已应用于您的索引文本,这意味着它永远不会匹配: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集成,则必须依靠hack来使“仅查询”分析器正常工作。见here。