[ElasticSearch从入门到场景实战]深入搜索之全文搜索

1,261 阅读5分钟

人生起起伏伏,有风光无限日,也有落魄失魂时,人在低谷时,唯有“熬过去,才会赢”

前言

上一篇文章我们讲了从dsl写法,到如何利用spring data ElasticSearch来代码实现java操作ElasticSearch,这一期我们继续讲解,官方文档中的深入搜索之全文搜索,望大家有所收获。

1. 基于词项与基于全文:

I. 基于词项的查询

我们都知道,ElasticSearch在存储字符串时,会将字符串根据自带分词器进行分词,而所谓基于词项的查询即是不分词查询,必须在整个词语完全匹配的情况下才显示结果,也就是我们常说并且常用到的精确查询。像term和fuzzy,它们的底层查询不需要分析操作,它们只对单个词组进行操作,例如term查询,它只会在倒排索引中精确查询准确词项。

II. 基于全文的查询

所谓全文查询,通俗来说就是全字段或者多字段查询,例如query_string和match_query,拿query_string来说,它就是全字段匹配,当你对一个字符串进行查询,它会将字符串传递到合适的字段进行查询,最终结果是会将所有字段,匹配到该字符串的数据全部显示。

2. 匹配搜索

匹配查询-match 是ElasticSearch的核心查询,在我们使用ElasticSearch的时候,无论何时,match都应该是我们优先选择的查询方式,它是一个高级的全文查询,同时具有分词查询和精确查询的能力。

DSL:
GET /demo/demodo/_search
{
    "query": {
        "match": {
            "name": "addb8e53"
        }
    }
}
SQL(不完全相等,SQL没有分词查询):
select * from demo where name = 'addb8e53'
Spring Data ElasticSearch:
QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "addb8e53")
out(queryBuilder);

刚才我们说了,match查询是一个高级的全文查询,同时具有分词查询和精确查询的能力,上面这段查询方式,用的就是分词查询,name字段是字符串类型,value我写的是一段UUID,分词器根据 - 进行了分词,addb8e53是这个UUID中的其中一段,所以我可以使用这种方式查询到多个包含这个分段的结果,如果我需要精确查询,则只需要在name后面加上一个.keyword即可,由"name": "addb8e53"变成"name.keyword": "addb8e53",spring data查询同理。

3. 多词查询

刚刚这种查询只是对这个字段进行了一次匹配,现在我们给name提供两个字符串来同时匹配。 下面这种查询,就是查出符合addb8e53 or 4d3029a6分词的结果。例如现在有 "name": "addb8e53-b504-499f-990b-5d73a35171e5" 和 "name": "4d3029a6-46f5-4b3b-afa2-3372ec2effcb" ,这时候这两个就会同时被查询出来。

DSL:
GET /demo/demodo/_search
{
    "query": {
    	"match": {
        	"name": "addb8e53 4d3029a6"
        }
    }
}
SQL(不完全相等,SQL没有分词查询):
select * from demo where name like '%addb8e53%' or name like '%4d3029a6%'
Spring Data ElasticSearch:
QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "addb8e53 4d3029a6");
out(queryBuilder);

除此之外,elasticsearch还提供了一种提高精度的查询,可以让查询结果,同时含有addb8e53和4d3029a6两个分词。elasticsearch给match提供了operator操作符,默认是or,这也就是我们为什么刚刚可以查出两个分词的结果,现在我们需要将or改成and,查出的结果就是必须同时存在两个分词的结果。

DSL:
GET /demo/demodo/_search
{
	"query": {
    	"match": {
           	"name": "addb8e53 4d3029a6",
           	"operator": "and"
        }
    }
}

4. 组合查询

之前我们有说过一个bool过滤器,bool过滤器提供了多个过滤条件,组合过滤器其实和bool过滤器差不多,用法和写法基本也是一样的,但查询更精确一些,组合查询 查询也可以接受 must 、must_not 和 should 参数下的多个查询语句,但是组合查询会给每个查询的文档计算相关度评分,将所有符合的 must 和 should 查询结果的评分求和,最后除以 must 和 should语句的总数。组合查询还提供了精度控制——minimum_should_match,它可以填写百分比或者数字来控制我们需要查询的should语句的精度,比如,我们现在should语句中有三条过滤条件,但是我们现在填写了minimum_should_match: 2,那么这个时候,查询结果中,符合should过滤两个条件的,要比符合should过滤三个条件的评分要高。

5. 如何使用布尔匹配

我们上面有说过分词查询,但是其实分词查询和如下的bool匹配是相等的:

DSL:
GET /demo/demodo/_search
{
	"query": {
        "bool": {
            "should": [
                {
                    "term": {
                        "name": "addb8e53"
                    }
                },
                {
                    "term": {
                        "name": "4d3029a6"
                    }
                }
            ]
        }
    }
}

注:match查询中也有minimum_should_match参数,如果有3个查询分词,minimum_should_match参数填写的是而,查询结果必须满足2个分词才会被显示

6. 查询语句提升权重

如下的DSL,就是提升权重的例子,我们控制should语句的权重,提供了boost参数,boost参数默认是1,数值越高权重越高,对应的评分越高

DSL:
{
	"query": {
        "bool": {
            "should": [
                {
                    "match": {
                    	"name": {
                    		"query": "addb8e53"
                    	}
                    }
                },
                {
                    "match": {
                    	"name": {
                    		"query": "4d3029a6",
                    		"boost": 4
                    	}
                    }
                }
            ]
        }
    }
}

添加权重前后比较如下图: 添加权重前:

添加权重后:

总结

很抱歉文章很久没有更新,这段时间疫情原因,公司一直都比较忙,最近压力也比较大,生活中也发生了一些事情,心情一直比较差,导致很久没有更新,在此和大家说声抱歉。还是一如既往的做最简单的文章,用最通俗的话语写清楚操作,希望大家喜欢。

1d539c0bf7d7bb104a29bf93ff2db6ed.png