1 ElasticSearch简介
ElasticSearch是一个基于Lucene库的分布式全文搜索引擎。提供Restful API操作接口,很方便使用。ElasticSearch是与名为Logstash的数据收集和日志解析引擎、以及名为Kibnana的分析和可视化平台一起开发的。这三个产品被设计成一个集成解决方案,称为“Elastic Stack”;ElasticSearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
1.1 ElasticSearch基本概念
- Index: 相当于mysql中的数据库;
- Type: 类似于mysql中的表,es中可以在Index中建立type(table),通过mapping进行映射;
- Document: 由于es中存储的数据是文档型的,一条数据对应一篇文档即相当于mysql数据库中的一行数据row,一个文档可以有多个字段也就是mysql数据库一行可以有多列。
- Mapping: 可以理解为mysql数据库中的表结构(schema);
1.2 ElasticSearch分析器
- 分析包含下面的过程:
(1)首先,将一块文本分成适合于倒排索引的独立的词条;
(2)之后,将这些词条统一化为标准格式以提高它们的可搜索性; - 分析器执行上面的工作,实际上是将三个功能封装到一个包里:
(1)字符过滤器: 首先,字符串按顺序通过每个字符过滤器。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 & 转化成 and;
(2)分词器: 其次,字符串被分词器分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条;
(3)Token过滤器: 最后,词条按顺序通过每个token过滤器。这个过程可能会改变词条,例如最小化、删除无用词、同义处理等; - Elasticsearch提供了开箱即用的字符过滤器、分词器和token过滤器。这些可以组合起来形成自定义的分析器以用于不同的目的。
1.2.1 内置分析器
- 标准分析器: 标准分析器是Elasticsearch默认使用的分析器。它是分析各种语言文本最常用的选择。它根据Unicode联盟定义的单词边界划分文本。删除绝大部分标点、将词条小写。
- 简单分析器: 简单分析器在任何不是字母的地方分隔文本,将词条小写。
- 空格分析器: 空格分析器在空格的地方划分文本。
- 语言分析器: 特定语言分析器可用于很多语言。它们可以考虑指定语言的特点。比如停用词、词干提取等。
1.2.2 什么时候使用分析器
- (1)当我们索引一个文档,它的全文域被分析成词条以用来创建 倒排索引;
- (2)当我们在全文域搜索的时候,我们需要将查询字符串通过相同的分析过程,以保证我们搜索的词条格式与索引中的词条格式一致。
2 ES常用查询语句
2.0 ES查询结果解释
-
took
字段表示该操作耗时,单位为毫秒; -
time_out
字段表示是否超时; -
hits
存储返回结果,下述例子返回2条结果; -
_source
表示相关性得分;Elasticsearch权威指南:什么是相关性?
{
"took":2,
"timed_out":false,
"_shards":{"total":5,"successful":5,"failed":0},
"hits":{
"total":2,
"max_score":1.0,
"hits":[
{
"_index":"accounts",
"_type":"person",
"_id":"AV3qGfrC6jMbsbXb6k1p",
"_score":1.0,
"_source": {
"user": "李四",
"title": "工程师",
"desc": "系统管理"
}
},
{
"_index":"accounts",
"_type":"person",
"_id":"1",
"_score":1.0,
"_source": {
"user" : "张三",
"title" : "工程师",
"desc" : "数据库管理,软件开发"
}
}
]
}
}
2.1 基础查询
- 查询mapping:
GET xxxxx/_mapping
2.2 精确值查询
- 按照poi_id精确查找:
term
GET xxxxx/_search
{
"query": {
"term": {
"poi_id": "xxxxx"
}
}
}
- 查找结果显示部分字段:
_source
GET xxxxx/_search
{
"query": {
"term": {
"poi_id": "xxxxx"
}
},
"_source": [ "name", "address"]
}
- 查询多个精确值:
terms
GET xxxxx/_search
{
"query": {
"terms": {
"name": ["xxxxx", "xxxxx"]
}
}
}
2.3 布尔查询
- 一个bool查询由三部分组成:
(1)must
所有的语句 都必须匹配,与AND等价;
(2)must_not
所有的语句 都不能匹配,与NOT等价;
(3)should
一个文档不必包含brown或dog这两个词,但如果一旦包含,我们就认为它们更相关;
GET xxxxx/_search
{
"query": {
"bool": {
"must": { "match": { "title": "quick" }},
"must_not": { "match": { "title": "lazy" }},
"should": [
{ "match": { "title": "brown" }},
{ "match": { "title": "dog" }}
]
}
}
}
- term查询与match查询等价转换,通过bool查询实现;
{
"match": {
"title": {
"query": "brown fox",
"operator": "and"
}
}
}
{
"bool": {
"must": [
{ "term": { "title": "brown" }},
{ "term": { "title": "fox" }}
]
}
}
2.4 范围查询
- 查询click_score在某个范围:
range
;其中gte
大于等于,lt
小于;
(1)gt: > 大于(greater than)
(2)lt: < 小于(less than)
(3)gte: >= 大于或等于(greater than or equal to)
(4)lte: <= 小于或等于(less than or equal to)
GET xxxxx/_search
{
"query": {
"range" : {
"click_score" : {
"gte" : xxx,
"lt" : xxx
}
}
}
}
2.5 基于词项与基于全文查询
- 基于词项查询: 例如term或fuzzy这样的底层查询不需要分析阶段,它们对单个词项进行操作。记住term查询只对倒排索引的词项精确匹配,这点很重要,它不会对词的多样性进行处理(如foo或Foo)。
- 基于全文的查询: match或query_string这样的查询是高层查询,它们了解字段映射的信息:
(1)如果查询日期或整数字段,它们会将查询字符串分别作为日期或整数对待;
(2)如果查询一个未分析的精确值字符串字段,它们会将整个查询字符串作为单个词项对待。
(3)如果查询一个已分析的全文字段,它们会先将查询字符串传递到一个合适的分析器,然后生成一个供查询的词项列表。一旦组成了词项列表,这个查询会对每个词项逐一执行底层的查询,再将结果合并,然后为每个文档生成一个最终的相关度评分。
2.6 匹配查询
- 匹配查询
match
是个核心查询。无论需要查询什么字段,match查询都应该会是首选的查询方式。它是一个高级全文查询,这表示它既能处理全文字段,又能处理精确字段。 - 匹配查询控制精度:
operator: or/and
、minimum_should_match: 75%
- 注意:
from, size
:实现分页功能;sort
:文档根据click_score
降序排序;
GET xxxxx/_search
{
"from": 0,
"query": {
"match": {
"name": {
"operator": "and",
"query": "xxxxx xxxxx"
}
}
},
"size": 20,
"sort": [
{
"click_score": {
"order": "desc"
}
}
]
}
2.7 multi_match查询
-
multi_match
查询为能在多个字段上反复执行相同查询提供了一种便捷方式。multi_match关键字的作用是可以使多个字段同时匹配一个关键字,fields属性声明需要查询哪些字段。
GET xxxxx/_search
{
"query": {
"multi_match" : {
"query" : "guide",
"fields" : ["title", "authors", "summary", "publish_date", "num_reviews", "publisher"]
}
}
}
- 提高某个字段的相关度,将summary这个字段的分数提高到3,增加这个字段的重要性;
GET xxxxx/_search
{
"query": {
"multi_match" : {
"query" : "elasticsearch guide",
"fields": ["title", "summary^3"]
}
},
"_source": ["title", "summary", "publish_date"]
}
2.8 模糊查询
- 模糊查询可以在
match
和multi_match
查询里使用,来解决用户拼写错误,模糊查询的程度声明基于原单词的莱文斯坦距离;即需要对一个字符串进行字符更改的数量,以使其与另外一个字符串相同。 -
fuzziness
字段除了设置为AUTO
,还可以设置为0,1,2等;
GET xxxxx/_search
{
"query": {
"multi_match" : {
"query" : "comprihensiv guide",
"fields": ["title", "summary"],
"fuzziness": "AUTO"
}
},
"_source": ["title", "summary", "publish_date"],
"size": 1
}
2.9 短句查询
- 短句查询(
match_phrase_prefix
)需要匹配所有单词才能被搜索出来,按照指定的顺序并且是连续的,默认情况下单词之间必须是连续的。但是你可以通过改写slop
的值来声明即便两个单词之间间隔多少个单词,该文档仍被匹配出来。
GET xxxxx/_search
{
"query": {
"match_phrase_prefix" : {
"summary": {
"query": "search en",
"slop": 3,
"max_expansions": 10
}
}
},
"_source": [ "title", "summary", "publish_date" ]
}
2.10 地理查询
- 限定召回数据距离在1km之内;
geo_distance
- 当我们使用布尔查询的时候,可以使用
filter
参数筛选一些结果。
GET xxxxx/_search
{
"query":{
"filtered": {
"query":{
"bool":{
"must":[
{
"match":{
"name": {
"query": "xxxxx xxxxx xxxxx",
"operator": "and"
}
}
},
{
"match":{
"category_code": "xxxxx"
}
}
]
}
},
"filter": {
"geo_distance": {
"distance": "1km",
"location": {
"lon": xxxxx,
"lat": xxxxx
}
}
}
}
},
"size": 10,
"from": 0,
"terminate_after": 200000
}
2.11 相关度函数
- 有时候你可能想要根据结果的某个字段的值,来提升这条数据在这次检索中的相关度。比较典型的是你希望根据数据的被关注度来提升检索相关度。在下面的例子中,我们希望通过 reviews 的数量来提升一条文档的相关度,可以通过
field_value_factor
函数实现;
GET xxxxx/_search
{
"query": {
"function_score": {
"query": {
"multi_match" : {
"query" : "search engine",
"fields": ["title", "summary"]
}
},
"field_value_factor": {
"field" : "num_reviews",
"modifier": "log1p",
"factor" : 2
}
}
},
"_source": ["title", "summary", "publish_date", "num_reviews"]
}
参考资料
- Elasticsearch: 权威指南 https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
(1)分析与分析器:https://www.elastic.co/guide/cn/elasticsearch/guide/current/analysis-intro.html#analysis-intro
(2)自定义分析器:https://www.elastic.co/guide/cn/elasticsearch/guide/current/custom-analyzers.html
(3)深入搜索:https://www.elastic.co/guide/cn/elasticsearch/guide/current/search-in-depth.html
(4)布尔过滤器:https://www.elastic.co/guide/cn/elasticsearch/guide/current/combining-filters.html
(5)什么是相关性?:https://www.elastic.co/guide/cn/elasticsearch/guide/current/relevance-intro.html
(6)地理距离过滤器:https://www.elastic.co/guide/cn/elasticsearch/guide/current/geo-distance.html
(7)模糊匹配查询:https://www.elastic.co/guide/cn/elasticsearch/guide/current/fuzzy-match-query.html
(8)排序:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_Sorting.html - 全文搜索引擎 Elasticsearch 入门教程
https://www.ruanyifeng.com/blog/2017/08/elasticsearch.html - 视频教程
(1)搜索引擎 ElasticSearch 视频教程全集(60P)| 10 小时从入门到精通
https://www.bilibili.com/video/av59628430/
(2)B站讲的最好的elasticsearch教程
https://www.bilibili.com/video/BV1kv411q7aS/?spm_id_from=333.788.videocard.0 - [搬运] 23 个例子让你彻底搞定 Elasticsearch 的搜索查询语法
https://ruby-china.org/topics/38431