// matchPhraseQuery短语匹配,只会匹配到相同短语的,对应ES文档的match_phrase
// weightFactorFunction 对文档进行了重新打分,改变排序规则,对应ES文档的function_score
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery()
.add(QueryBuilders.matchPhraseQuery("name", searchContent),
ScoreFunctionBuilders.weightFactorFunction(1000))
.add(QueryBuilders.matchPhraseQuery("description", searchContent),
ScoreFunctionBuilders.weightFactorFunction(500))
.scoreMode(SCORE_MODE_SUM).setMinScore(MIN_SCORE);
// 分页参数
Pageable pageable = new PageRequest(pageNumber, pageSize);
return new NativeSearchQueryBuilder()
.withPageable(pageable)
.withQuery(functionScoreQueryBuilder).build();
1、精确值查找(单个过滤器查找)
当进行精确值查找时, 我们会使用过滤器(filters)。过滤器很重要,因为它们执行速度非常快,不会计算相关度(直接跳过了整个评分阶段)而且很容易被缓存
term
查询对于查找单个值非常有用, 可以用它处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。
当不希望对查询进行评分计算(不明白什么叫评分计算)。只希望对文档进行包括或排除的计算,所以我们会使用 constant_score
查询以非评分模式来执行 term
查询并以一作为统一评分。
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"price" : 20
}
}
}
}
}
执行后,这个查询所搜索到的结果与我们期望的一致:只有文档 2 命中并作为结果返回(因为只有 2
的价格是 20
):
"hits" : [
{
"_index" : "my_store",
"_type" : "products",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"price" : 20,
"productID" : "KDKE-B-9947-#kL5"
}
}
]
"_score" : 1.0:查询置于 filter
语句内不进行评分或相关度的计算,所以所有的结果都会返回一个默认评分 1
。
2、多个值查找(布尔)过滤器
bool
(布尔)过滤器。 这是个 复合过滤器(compound filter) ,它可以接受多个其他过滤器作为参数,并将这些过滤器结合成各式各样的布尔(逻辑)组合。
一个 bool
过滤器由三部分组成:
{
"bool" : {
"must" : [],
"should" : [],
"must_not" : [],
}
}
must
所有的语句都 必须(must) 匹配,与 AND
等价。
must_not
所有的语句都 不能(must not) 匹配,与 NOT
等价。
should
至少有一个语句要匹配,与 OR
等价。
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"price" : 20}},
{ "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
],
"must_not" : {
"term" : {"price" : 30}
}
}
}
}
}
}
3、查找多个精确值,使用terms
{
"query" : {
"constant_score" : {
"filter" : {
"terms" : {
"price" : [20, 30]
}
}
}
}
}
这个 terms
查询被置于 constant_score
查询中
term
和 terms
是 包含(contains) 操作,而非 等值(equals)
范围搜索
ange
查询可同时提供包含(inclusive)和不包含(exclusive)这两种范围表达式,可供组合的选项如下:
gt
: >
大于(greater than)lt
: <
小于(less than)gte
: >=
大于或等于(greater than or equal to)lte
: <=
小于或等于(less than or equal to)"range" : {
"price" : {
"gte" : 20,
"lte" : 40
}
}
dis_max查询
不使用 bool
查询,可以使用 dis_max
即分离 最大化查询(Disjunction Max Query) 。分离(Disjunction)的意思是 或(or) ,这与可以把结合(conjunction)理解成 与(and) 相对应。分离最大化查询(Disjunction Max Query)指的是: 将任何与任一查询匹配的文档作为结果返回,但只将最佳匹配的评分作为查询的评分结果返回 :
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "Brown fox" }},
{ "match": { "body": "Brown fox" }}
]
}
}
}
dis_max
查询只会简单地使用 单个 最佳匹配语句的评分 _score
作为整体评分。使用dis_max,_score
的评分是一致的
可以通过指定 tie_breaker
这个参数将其他匹配语句的评分也考虑其中
{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "Quick pets" }},
{ "match": { "body": "Quick pets" }}
],
"tie_breaker": 0.3
}
}
}
tie_breaker
参数提供了一种 dis_max
和 bool
之间的折中选择,它的评分方式如下:
_score
。tie_breaker
相乘。有了 tie_breaker
,会考虑所有匹配语句,但最佳匹配语句依然占最终结果里的很大一部分。
tie_breaker
可以是 0
到 1
之间的浮点数,其中 0
代表使用 dis_max
最佳匹配语句的普通逻辑, 1
表示所有匹配语句同等重要。最佳的精确值需要根据数据与查询调试得出,但是合理值应该与零接近(处于 0.1 - 0.4
之间),这样就不会颠覆 dis_max
最佳匹配性质的根本。
匹配查询
匹配查询 match
是个 核心 查询。无论需要查询什么字段, match
查询都应该会是首选的查询方式。 它是一个高级 全文查询 ,这表示它既能处理全文字段,又能处理精确字段。
这就是说, match
查询主要的应用场景就是进行全文搜索
{
"query": {
"match": {
"title": "QUICK!"
}
}
}
match支持多词查询,如
{
"query": {
"match": {
"title": "BROWN DOG!"
}
}
}
match
查询必须查找两个词( ["brown","dog"]
),它在内部实际上先执行两次 term
查询,然后将两次查询的结果合并作为最终结果输出。为了做到这点,它将两个 term
查询包入一个 bool
查询中,详细信息见 布尔查询。
以上示例告诉我们一个重要信息:即任何文档只要 title
字段里包含 指定词项中的至少一个词 就能匹配,被匹配的词项越多,文档就越相关。
提高match查询的精度
不去定义match的查询类型,默认情况下操作符是or,也就是brown or dog,如果需要精确匹配,需要定义为and,则
{
"query": {
"match": {
"title": {
"query": "BROWN DOG!",
"operator": "and"
}
}
}
}
控制match查询的精度
match
查询支持 minimum_should_match
最小匹配参数, 这让我们可以指定必须匹配的词项数用来表示一个文档是否相关。我们可以将其设置为某个具体数字,更常用的做法是将其设置为一个百分数,因为我们无法控制用户搜索时输入的单词数量:
{
"query": {
"match": {
"title": {
"query": "quick brown dog",
"minimum_should_match": "75%"
}
}
}
}
多数字段匹配 任意 词 most_fields
为每个字段重复查询字符串会使查询瞬间变得冗长,可以采用 multi_match
查询, 将 type
设置成 most_fields
然后告诉 Elasticsearch 合并所有匹配字段的评分:
{
"query": {
"multi_match": {
"query": "Poland Street W1V",
"type": "most_fields",
"fields": [ "street", "city", "country", "postcode" ]
}
}
}
用 most_fields
这种方式搜索也存在某些问题,这些问题并不会马上显现:
operator
或 minimum_should_match
参数来降低次相关结果造成的长尾效应。
参考网址:https://blog.csdn.net/zxjiayou1314/article/details/53185287(通过Function Score Query优化Elasticsearch搜索结果)
https://es.yemengying.com/5/5.3/5.3.2.html(使用Spring data elasticSearch)
【注意点:如果使用过滤器查询ES数据的话,则返回的_score默认都设置为1,这时候我们可以通过function_score改变权重,找到我们想要的信息】