ES学习笔记——初识ElasticSearch

ElasticSearch介绍

ES是一个使用Java语言并且基于Lucene编写的搜索引擎框架,它提供了分布式的全文搜索功能,提供了一个统一的基于RESTful风格的WEB接口,官方客户端也对多种语言都提供了相应的API。

  • Lucene:本身就是一个搜索引擎的底层。直接使用成本高。官网地址:https://lucene.apache.org/
  • 分布式:突出的横向扩展能力(集群)
  • 全文检索:将一段词语进行分词,并且将分出的单个词语统一的放到分词库中,在搜索时,根据关键字去分词库中检索,找到匹配的内容。(倒排索引)eg:将“我爱编程”这个词语拆分成“我”、“爱”、“编程”,在搜索“爱我中华”的时候会将搜索内容拆分成“爱”、“我”、“中华”等,去分词库中查询有没有匹配的单个词。
  • RESTful风格接口:操作简单,只需要发送一个HTTP请求,并且根据请求方式以及携带参数的不同来执行不同的操作。
  • 倒排索引
    1. 将存放的数据,以一定的方式进行分词,并且将分词的内容存放到一个单独的分词库中。
    2. 当用户去查询数据时,会将用户查询的关键字进行分词。
    3. 然后去分词库匹配内容,最终得到数据的id标识。
    4. 根据id标识去存放数据的位置拉取到指定的数据。
      在这里插入图片描述

ElasticSearch安装

  1. 在/opt/es_docker下新建docker-compose.yml,内容如下:
version: '2'
services:
  elasticsearch:
    container_name: elasticsearch
    image: daocloud.io/library/elasticsearch:7.7.0
    ports:
      - "9200:9200"
    environment:
      - "ES_JAVA_OPTS=-Xms64m -Xmx128m"
      - "discovery.type=single-node"
      - "COMPOSE_PROJECT_NAME=elasticsearch-server"
    restart: always

  kibana:
    container_name: kibana
    image: daocloud.io/library/kibana:7.7.0
    ports:
      - "5601:5601"
    restart: always
    environment:
      - ELASTICSEARCH_HOSTS=http://192.168.127.188:9200

注意填写自己的IP地址。
2. 执行docker-compose up -d
3. 验证安装成功
分别在浏览器中输入http://192.168.127.188:9200/、http://192.168.127.188:5601/当看见以下内容时说明安装成功
在这里插入图片描述
在这里插入图片描述

IK分词器安装

ES默认的分词器会将每一个中文都进行分词,这样分词就没有什么意义了。

ES基本操作

分片和备份

在这里插入图片描述

ES中Field支持的类型

字符串:

  • text:被用于全文检索,将当前Field进行分词。eg:商品描述。
  • keyword:当前Field不会被分词。eg:地名。
    数值:
  • long
  • integer
  • short
  • byte
  • double
  • float
  • half_float
  • scaled_float:根据一个long和scaled来表达一个浮点类型,eg:long=345,scaled=100,对应结果3.45
    时间:
  • date:可以指定具体的格式
    布尔类型:
  • boolean
    二进制类型:
  • binary类型支持Base64 encode string
    范围类型:
  • long_range:指定gt,lt,gte,lte即可
  • float_range
  • double_range
  • date_range
  • ip_range
    经纬度类型:
  • geo_point:用来存储经纬度
    IP类型
  • ip_range:可以存储IPV4或者IPV6
    其他数据类型参考官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

创建索引并指定数据结构

PUT /book
{
  "settings": {
    "number_of_replicas": 1, #备份数
    "number_of_shards": 5 #分片数
  },
  # 指定数据结构
  "mappings": {
  	# 文档存储的Field
    "properties": {
      # Field名
      "name": {
      	# 类型
        "type": "text",
        # 指定分词器
        "analyzer": "ik_max_word",
        # 指定当前Field可以作为查询条件
        "index": true,
        # 是否需要额外存储
        "store": false
      },
      "author": {
        "type": "keyword"
      },
      "count": {
        "type": "long"
      },
      "onSale": {
        "type": "date",
        "format": [
          # 时间格式化方式
          "yyyy-MM-dd HH:mm:ss"
        ]
      },
      "desc": {
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}

文档操作

文档在ES服务中的唯一标识,_index,_doc,_id三个内容为组合,锁定一个文档。

新建文档
		# 添加文档,自动生成id
		POST /book/_doc
		{
		  "name":"风声",
		  "author":"麦家",
		  "onSale":"2020-07-23 00:00:00",
		  "desc":"经历过大孤独、大绝望的人,会懂得《风声》给你的大坚韧和大智慧。",
		  "count":123902
		}
		# 添加文档,手动指定id
		PUT /book/_doc/1
		{
		  "name":"繁花",
		  "author":"金宇澄",
		  "onSale":"2010-02-12 00:00:00",
		  "desc":"矛盾文学奖获奖作品",
		  "count":83902
		}
修改文档
		#覆盖修改
		PUT /book/_doc/1
		{
		  "name":"繁花",
		  "author":"金宇澄",
		  "onSale":"2010-02-12 00:00:00",
		  "desc":"矛盾文学奖获奖作品",
		  "count":2383902
		}
		#修改文档,基于doc方式
		POST /book/_doc/1/_update
		{
		  "doc":{
		    "count":1234567
		  }
		}
删除文档
	# 根据id删除文档
	DELETE /book/_doc/tOMn73UB90LCY1QIu_nJ

Java操作ES的几种方式可以看看这篇文章
https://blog.csdn.net/jacksonary/article/details/82729556

ES的各种查询

term&terms查询

term查询代表完全匹配,搜索之前不会对搜索的关键字进行分词,直接去分词库中匹配,找到相应的文档。
在这里插入图片描述
terms和term的查询机制是一样的,都不会将指定的关键字进行分词,直接去分词库中匹配,找到相应的文档内容。terms是用一个字段去匹配多个值的时候使用。
term:where province = 北京
terms:where province = 北京 or province = 深圳
在这里插入图片描述

match查询

match查询会根据查询的字段类型不一样,采用不同的查询方式。

  • 查询的是日期或者数值的话,将会把查询的字符串内容转换为日期或者数值对待。
  • 如果查询的是一个不能被分词的内容(keyword),match查询不会对指定的查询关键字进行分词。
  • 如果查询的内容是一个可以被分词的内容(text),match会将指定的查询内容根据一定的方式分词,去分词库中匹配指定的内容。

match查询,实际底层就是多个term查询,将多个term查询的结果分装到了一起。

指定一个Field作为筛选条件

image-20201129150826522

image-20201129150956950

布尔match查询

基于一个Field匹配的内容,采用and或者or的方式连接

image-20201129164453215

multi_match查询

match针对一个filed做检索,multi_match针对多个field进行检索,多个filed对应一个text,多个字段是or的关系。

image-20201129165318334

match_all查询

查询全部内容,不指定任何查询条件。

image-20201129150200803

其他查询
id查询

根据id查询 where id = ?

image-20201129165942968

ids查询

根据多个id查询,where id in (?,?,…)

image-20201129170438736

prefix查询

前缀查询,可以通过一个关键字去指定一个分词(text)field的前缀,从而查询到指定的文档。where field like ?%

image-20201129171106154

fuzzy查询

模糊查询,我们输入大概的字符,ES就可以根据输入的内容大概去匹配一下结果。

image-20201129172039043

可以通过prefix_length指定需要精确匹配的长度。

image-20201129172224685

wildcard查询

通配查询,可以在查询时,在字符串中指定通配符*和占位符?

image-20201129172942933

range查询

范围查询,只针对数值类型,对某一个filed进行大于或者小于的范围指定。

image-20201129173434759

regexp查询

正则查询,通过正则表达式匹配内容。

ps:prefix,fuzzy,wildcard和regexp查询效率相对term,terms比较低,要求效率比较高时避免使用。

image-20201129181054328

深分页Scroll

ES对from+size是有限制的,from和size二者之和不能超过1W

查询原理:

from+size在ES查询数据的方式:

  1. 将用户指定的关键字进行分词。
  2. 将分词结果去分词库中检索,得到多个文档的id。
  3. 去各个分片中拉取指定的数据。(耗时较长)
  4. 将数据根据score进行排序。(耗时较长)
  5. 根据from的值,将查询到的数据舍弃一部分。
  6. 返回结果

scroll+size在ES查询数据的方式:

  1. 将用户指定的关键字进行分词。
  2. 将分词结果去分词库中检索,得到多个文档的id。
  3. 将文档的id存放在一个ES的上下文中。
  4. 根据指定的size去ES中检索指定个数的数据,拿到数据的文档id,会从上下文中移除。
  5. 如果需要下一页数据,直接去ES的上下文中找后续内容。(重复4、5)
    scroll查询方式,不适合做实时的查询(将文档id存在内存中)
# 执行scroll查询,zhiidng返回第一页数据,并且将文档id信息存放在ES上下文中,指定有效时长1分钟
GET province/_search?scroll=1m	#指定文档id在内存中的存储时间
{
  "query": {					#查询条件
    "match_all": {}
  },
  "size": 2,					#每一页大小
  "sort": [						#排序
    {
      "code": {
        "order": "asc"
      }
    }
  ]
}

image-20201129212709962

# 根据上一页返回的scroll,查询下一页数据,同时指定文档id在内存中的有效时长
GET _search/scroll
{
"scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoBRRoYTR1RkhZQnI5Z1BPU0dWMnhZcAAAAAAAAADZFm9NUWx2YVM4U2E2M1NsZGt2VmRuMXcUaHE0dUZIWUJyOWdQT1NHVjJ4WXAAAAAAAAAA2xZvTVFsdmFTOFNhNjNTbGRrdlZkbjF3FGlLNHVGSFlCcjlnUE9TR1YyeFlwAAAAAAAAANwWb01RbHZhUzhTYTYzU2xka3ZWZG4xdxRoNjR1RkhZQnI5Z1BPU0dWMnhZcAAAAAAAAADaFm9NUWx2YVM4U2E2M1NsZGt2VmRuMXcUaWE0dUZIWUJyOWdQT1NHVjJ4WXAAAAAAAAAA3RZvTVFsdmFTOFNhNjNTbGRrdlZkbjF3",
  "scroll":"1m"
}

image-20201129212754226

# 删除scroll在ES上下文中的数据
DELETE _search/scroll/FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoBRRoYTR1RkhZQnI5Z1BPU0dWMnhZcAAAAAAAAADZFm9NUWx2YVM4U2E2M1NsZGt2VmRuMXcUaHE0dUZIWUJyOWdQT1NHVjJ4WXAAAAAAAAAA2xZvTVFsdmFTOFNhNjNTbGRrdlZkbjF3FGlLNHVGSFlCcjlnUE9TR1YyeFlwAAAAAAAAANwWb01RbHZhUzhTYTYzU2xka3ZWZG4xdxRoNjR1RkhZQnI5Z1BPU0dWMnhZcAAAAAAAAADaFm9NUWx2YVM4U2E2M1NsZGt2VmRuMXcUaWE0dUZIWUJyOWdQT1NHVjJ4WXAAAAAAAAAA3RZvTVFsdmFTOFNhNjNTbGRrdlZkbjF3

image-20201129213003492

delete_by_query

根据term,match等查询方式删除文档

PS:如果需要删除的内容是index下的大部分数据(删除比较耗时),推荐创建一个新的index,将保留的文档内容添加到新的索引

image-20201129222118568

复合查询
bool查询

复合过滤器,可以将多个查询条件以一定的逻辑组合在一起。

  • must:表示必须匹配。
  • must_not:表示必须不匹配。
  • should:当查询中没有must语句时,至少需要匹配一个should。默认情况下should语句可以一个都不匹配。

image-20201129225159039

booting查询

boosting查询会影响查询后的score

  • positive:只有匹配上positive的查询内容,才会被放到返回的结果集中。
  • negative:如果同时匹配上了positive和negative,就会降低文档的score。
  • negative_boost:指定系数,必须小于1.0。同时匹配positive和negative分数乘以negative_boost。
  • 必须同时指定以上三个条件。

查询时的分数计算:

  • 搜索的关键字在文档中出现的频次越高,分数越高。
  • 文档的内容越短,分数越高。
  • 搜索时指定的关键字会被分词,被分词的内容,被分词库匹配的个数越多,分数越高。

image-20201205153359850

image-20201205153453776

filter查询

query:根据查询条件,计算文档的匹配度得到一个分数,并且根据分数进行排序,不会做缓存。

filter:根据查询条件去查询文档,不会计算分数,而且会对经常被过滤的数据进行缓存。

image-20201205155241678

高亮查询

高亮查询以一定的特殊样式将用户输入的关键字展示出来。

ES的highlight属性

  • 和query同级别

  • fragment_size:指定高亮数据展示多少字符。

  • pre_tag:指定前缀标签,eg:

  • post_tag:指定后缀标签,eg:

  • fields:指定哪些field以高亮形式放回

image-20201205161252313

聚合查询

ES的聚合查询相比MYSQL要强大,ES提供的数据统计方式多种多样。

GET index/_search
{
    "aggs":{ #聚合查询关键字
        "agg":{ #聚合查询的名字
            "agg_type":{ #聚合查询的类型
                "属性":"值"
            }
        }
    }
}
去重统计

cardinality,将返回文档中的一个指定filed去重,统计一共有多少条数据。

image-20201205163259432

范围统计

统计指定field在一定范围内出现的文档个数。可以统计数值类型range、时间类型date_range、IP类型ip_range。

from:>=

to:<

image-20201205164441580

统计聚合查询

extended_stats,查询指定field的最大值、最小值、平均值、平方和…

image-20201205165031093

地图经纬度搜索

检索方式

  • geo_distance:以一个点为中心,一定距离为半径的圆,获取在圆形内的全部数据。
  • geo_bounding_box:以两点连线为对角线确定一个矩形,获取在矩形内的全部数据。
  • geo_polygon:以多个点确定一个多边形,获取多边形内的全部数据。
geo_distance
GET city/_search
{
  "query": {
    "geo_distance": {
      "location": {	#指定属性,确定一个点
        "lon": 116.397128,
        "lat": 39.916527
      },
      "distance": 3000,	#确定半径
      "distance_type": "arc"	#确定形状
    }
  }
}

image-20201205172249072

geo_bounding_box
GET city/_search
{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": { #左上角坐标
          "lon": 115.06640900585936,
          "lat": 40.595651124351214
        },
        "bottom_right": { #右下角坐标
          "lon": 116.6237210175781,
          "lat": 39.69709306733553
        }
      }
    }
  }
}

image-20201205173118657

geo_polygon

image-20201205173709763

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值