我正在尝试在下面的文字列表中搜索<strong> blue 这个词
&#34; BlueSaphire&#34;,&#34; Bluo&#34;,&#34; alue&#34;,&#34; blue&#34;,&#34; BLUE&#34;, &#34; Blue&#34;,&#34; Blue Black&#34;,&#34; Bluo&#34;,&#34; Saphire Blue&#34;, &#34;黑色&#34; ,&#34;绿色&#34;,&#34; bloo&#34; ,&#34; Saphireblue&#34;
SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("color")
.withQuery(matchQuery("colorDescriptionCode", "blue")
.fuzziness(Fuzziness.ONE)
)
.build();
此工作正常,搜索结果返回以下记录以及分数
alue 2.8718023
Bluo 1.7804208
Bluo 1.7804208
BLUE 1.2270637
blue 1.2270637
Blue 1.2270637
Blue Black 1.1082436
Saphire Blue 0.7669148
但我无法制作外卡。 &#34; SaphireBlue&#34;和&#34; BlueSaphire&#34;预计也将成为结果的一部分
我尝试了以下设置,但它不起作用。
SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("color")
.withQuery(matchQuery("colorDescriptionCode", "(.*?)blue")
.fuzziness(Fuzziness.ONE)
)
.build();
在堆栈溢出中,我观察到一个解决方案来指定分析通配符。
QueryBuilder queryBuilder = boolQuery().should(
queryString("blue").analyzeWildcard(true)
.field("colorDescriptionCode", 2.0f);
我找不到queryString静态方法。我正在使用spring-data-elasticsearch 2.0.0.RELEASE。
让我知道如何指定外卡,以便在搜索结果中也会返回包含 blue 的所有字词
答案 0 :(得分:0)
我无法在一个查询中实现模糊和威尔卡搜索。
这是我能得到的最接近的解决方案。我不得不触发两个不同的查询并手动合并结果。
@Query("{\"wildcard\" : {\"colorDescriptionCode\" : \"?0\" }}")
Page<ColorDescription> findByWildCard(String colorDescriptionCode, Pageable pageable);
@Query("{\"match\": { \"colorDescriptionCode\": { \"query\": \"?0\", \"fuzziness\": 1 }}}")
Page<ColorDescription> findByFuzzy(String colorDescriptionCode, Pageable pageable);
答案 1 :(得分:0)
我知道工作的例子总是比理论好,但我仍然想先讲一点理论。 Elasticsearch的核心是Lucene。因此,在将文档写入Lucene索引之前,他将经历分析阶段。分析阶段可分为3个部分:
在第一阶段,我们可以丢弃不需要的字符,例如HTML标记。有关字符过滤器的更多信息,您可以在official site上找到。 下一阶段更有趣。在这里,我们将输入文本拆分为标记,稍后将用于搜索。一些非常有用的tokenizers:
"fo", "or", "r ", " e", "ex", "for", "or ex"
等.n-gram的长度是可变的,可以由min_gram和max_gram params配置。 "fo", "for", "for ", "for e", "for ex", "for exa"
等。
有关您可以在官方网站上找到的tokenizer的更多信息。不幸的是,由于声誉不佳,我无法发布更多链接。下一阶段也很有意思。在我们将文本拆分为令牌之后,我们可以用这个做很多有趣的事情。我再次举几个非常有用的令牌过滤器示例:
如果您有兴趣查看分析仪的结果,可以使用此_termvectors端点
curl [ELASTIC_URL]:9200/[INDEX_NAME]/[TYPE_NAME]/[DOCUMENT_ID]/_termvectors?pretty
现在谈谈查询。查询分为2大组。这些群体有两个显着差异:
示例是匹配查询和术语查询。第一个将通过分析阶段,第二个不会。第一个不会给我们一个具体的答案(但给我们一个分数),第二个会给我们一个答案。在为文档创建映射时,我们可以为每个字段分别指定分析器的索引和搜索分析器。
现在有关弹簧数据弹性搜索的信息。在这里谈谈具体的例子是有意义的。假设我们有一个带有标题字段的文档,我们想要搜索有关该字段的信息。首先,创建一个包含elasticsearch设置的文件。
{
"analysis": {
"analyzer": {
"ngram_analyzer": {
"tokenizer": "ngram_tokenizer",
"filter": [
"lowercase"
]
},
"edge_ngram_analyzer": {
"tokenizer": "edge_ngram_tokenizer",
"filter": [
"lowercase"
]
},
"english_analyzer": {
"tokenizer": "standard",
"filter": [
"lowercase",
"english_stop",
"unique",
"english_possessive_stemmer",
"english_stemmer"
]
"keyword_analyzer": {
"tokenizer": "keyword",
"filter": ["lowercase"]
}
},
"tokenizer": {
"ngram_tokenizer": {
"type": "ngram",
"min_gram": 2,
"max_gram": 20
},
"edge_ngram_tokenizer": {
"type": "edge_ngram",
"min_gram": 2,
"max_gram": 20
}
},
"filter": {
"english_stop": {
"type": "stop",
"stopwords": "_english_"
},
"english_stemmer": {
"type": "stemmer",
"language": "english"
},
"english_possessive_stemmer": {
"type": "stemmer",
"language": "possessive_english"
}
}
}
您可以将此设置保存到资源文件夹中。现在让我们看看我们的文档类
@Document(indexName = "document", type = "document")
@Setting(settingPath = "document_index_setting.json")
public class Document {
@Id
private String id;
@MultiField(
mainField = @Field(type = FieldType.String,
index = not_analyzed),
otherFields = {
@InnerField(suffix = "edge_ngram",
type = FieldType.String,
indexAnalyzer = "edge_ngram_analyzer",
searchAnalyzer = "keyword_analyzer"),
@InnerField(suffix = "ngram",
type = FieldType.String,
indexAnalyzer = "ngram_analyzer"),
searchAnalyzer = "keyword_analyzer"),
@InnerField(suffix = "english",
type = FieldType.String,
indexAnalyzer = "english_analyzer")
}
)
private String title;
// getters and setters omitted
}
所以这里有三个内部字段的字段标题:
title.edge_ngram
使用关键字搜索分析器搜索边缘n-gram。我们需要这个,因为我们不需要将查询拆分为edge n-gram; title.ngram
用于搜索n-gram; title.english
用于搜索自然语言的细微差别
和主要领域的标题。我们不分析这个,因为有时我们想要按此字段排序。
让我们使用简单的多匹配查询来搜索所有这些字段:String searchQuery = "blablabla"; MultiMatchQueryBuilder queryBuilder = multiMatchQuery(searchQuery) .field("title.edge_ngram", 2) .field("title.ngram") .field("title.english"); NativeSearchQueryBuilder searchBuilder = new NativeSearchQueryBuilder() .withIndices("document") .withTypes("document") .withQuery(queryBuilder) .withPageable(new PageRequest(page, pageSize)); elasticsearchTemplate.queryForPage(searchBuilder.build, Document.class, new SearchResultMapper() { //realisation omitted });
搜索是一个非常有趣和丰富的主题。我试图尽可能简短地回答,因为这可能会有令人困惑的时刻 - 请不要犹豫。