因为工作太忙,没有时间排版,原版本是自己总结的word,有需要请私信我。
基础概念
Elasticsearch对应MySQL的对应关系如下:
Elasticsearch |
MySQL |
索引库(indices) |
Database 数据库 |
类型(type) |
Table 数据表 |
文档(Document) |
Row 行 |
域字段(Field) |
Columns 列 |
映射配置(mappings) |
每个列的约束(类型、长度) |
对Elasticsearch相关概念说明:
概念 |
说明 |
索引库(indices) |
indices是index的复数,代表许多的索引 |
类型(type) |
类型是模拟mysql中的table概念,一个索引库下可以有不同类型的索引(目前6.X以后的版本只能有一个类型),类似数据库中的表概念。数据库表中有表结构,也就是表中每个字段的约束信息;索引库的类型中对应表结构的叫做映射(mapping),用来定义每个字段的约束。 |
文档(document) |
存入索引库原始的数据。比如每一条商品信息,就是一个文档 |
字段(field) |
文档中的属性 |
映射配置(mappings) |
字段的数据类型、属性、是否索引、是否存储等特性 |
一、索引
PUT 代表创建请求有幂等性,多次请求只会有一次成功
- 创建索引:
创建名称为shopping的索引。
- PUT Http:127.0.0.1:9200/shopping
2.通过索引名称查看索引的信息:
- GET Http:127.0.0.1:9200/shopping
3.查看所有的索引信息:
- GET Http:127.0.0.1:9200/_cat/indices?V
- 通过索引名称删除索引:
- Delete Http:127.0.0.1:9200/shopping
二、文档操作
Mysql增加数据需要表,ES新版本中直接在索引中添加数据
- 新增文档:
- POST Http:127.0.0.1:9200/shopping/_doc
- {
- “title”:”添加的第一个文档”,
- “msg”:”添加成功”
- }
必须要以JSON格式为请求体,没有请求ES会报错。不可以用PUT请求,因为新增文档请求成功后会返回一串消息,消息里面的_id是不同的,也就是说同样的请求都会返回不同的结果。
新增文档时给文档设置我们自己的id,而不是ES自动生成的UUID:
- POST Http:127.0.0.1:9200/shopping/_doc/1001
- {
- “title”:”添加的第一个文档”,
- “msg”:”添加成功”
- }
创建id为1001的一条JSON文档。因为id是我们确定后自定义的,这时候就可以用PUT请求创建了,幂等性问题解决。
- PUT Http:127.0.0.1:9200/shopping/_doc/1001
- {
- “title”:”添加的第一个文档”,
- “msg”:”添加成功”
- }
总结: 自定义ID可以用POST或者PUT,ES生成UUID就只能用POST。
- 根据id查询文档:
- Get Http:127.0.0.1:9200/shopping/_doc/1001
Shopping 代表索引的名称,_doc代表文档,1001是文档的id。查询id为1001的文档
- 查询索引下的所有文档:
- Get Http:127.0.0.1:9200/shopping/_search
4.修改文档:
分为两种情况,1-完全覆盖,2-部分数据修改(局部更新)
4.1完全覆盖:返回的消息都是一定的所以可以用PUT请求:
- PUT Http:127.0.0.1:9200/shopping/_doc/1001
- {
- “title”:”修改的第一个文档,V_2”,
- “msg”:”修改成功V_2”
- }
完全覆盖掉id为1001的文档
4.2部分数据修改(局部更新),每次返回的消息都可能不一样,所以用POST请求
- PUT Http:127.0.0.1:9200/shopping/_update/1001
- {
- “doc” :{
- “title”:”局部更新第一个文档,V_2”,
- }
- }
局部更新id为1001的title名称,而msg不更新。
5删除文档:
- DELETE Http:127.0.0.1:9200/shopping/_doc/1001
在shpping索引中删除文档(_doc就是文档的意思)id为1001的文档
三、复杂查询
在索引中通过条件,查询索引内部的符合条件的文档。返回的结果集合中,took值表示查询响应使用了多少毫秒。
1.简单条件全查询(match_all)
-
- url路劲条件查询(不推荐)
因为url路径中带有中文,可能会出现乱码所以推荐把请求参数写入到http的Body请求体中。
- Get Http:127.0.0.1:9200/shopping/_search?q=title:局部更新第一个文档,V_2
q代表query查询条件的简写。q为key ,”title:局部更新第一个文档,V_2”为value。查询出“title”为“局部更新第一个文档,V_2”的值。
1.2 Body请求体分页查询
因为url路径中带有中文,可能会出现乱码所以推荐把请求参数写入到http的Body请求体中。
- Get Http:127.0.0.1:9200/shopping/_search?q=title:局部更新第一个文档,V_2
- {
- "query" :{
- "match_all" :{
- }
- },
- "from": 0,
- "size": 2,
- "_source": {msg},
- "sort" : {
- "create_time" : {
- "order" : "desc"
- }
- }
- }
Match_all代表全查询(检索出所有文档),form表示起始页,size表示每页大小,_source表示过滤——只检索出文档中的msg字段,sort表示排序,对文档中的create_time字段进行降序排序。
- 多条件查询
2.1 条件同时成立must
- {
- "query" :{
- "bool" : {
- "must" : [
- "match" : {
- "msg": "msg字段第一次使用多条件查询"
- },
- "match" : {
- "title": "title字段第一次使用多条件查询"
- }
- ]
- }
- }
- }
query表示查询,多个条件使用bool包裹,must表示必须成立(与sql中的and相似),match表示匹配,在文档中查询msg等于 "msg字段第一次使用多条件查询" 并且条件 msg等于 "title字段第一次使用多条件查询" 的数据记录。
2.2 匹配一个条件(类似sql的or)shold
- {
- "query" :{
- "bool" : {
- "should" : [
- "match" : {
- "msg": "msg字段第一次使用多条件查询"
- },
- "match" : {
- "title": "title字段第一次使用多条件查询"
- }
- ]
- }
- }
- }
should字段类似于sql当中的or查询, 查询出文档内“msg”等于"msg字段第一次使用多条件查询" 或者 "title"等于"title字段第一次使用多条件查询"的字段。
2.3 条件过滤filter
- {
- "query" :{
- "bool" : {
- "must" : [
- "match" : {
- "msg": "第一次使用多条件查询"
- },
- "match" : {
- "title": "title字段第一次使用多条件查询"
- }
- ],
- "filter" : {
- "range" : {
- "create_time" :2021-5-29
- }
- }
- }
- }
- }
继续在2.2的基础上增加操作,使用filter过滤出create_time在2021-5-29的范围(range)内的文档。
- 完全匹配(match_phrase)
ES底层的索引机制为倒排索引,索引记载了哪些文档包含某个单词,单词为key,key的value值记载的是文档的ids(多个文档的id如:1,2,3,4,5)以及词频率(TF)和地址(POS)。如2.3.3代码块,条件key -"msg" 、value-"第一次使用多条件查询" 在ES中会对value进行分词,可能拆分为“第一次”、“使用”、“多条件”、“查询”,只要msg中包含其中一项就会命中。可是,如果想要他底层不进行分词检索,这时候就要把match改为match_phrase。
- {
- "query" :{
- "match_phrase" :{
- "msg": "第一次使用多条件查询"
- }
- },
- }
- 高亮显示
- {
- "query" :{
- "match_phrase" :{
- "msg": "第一次使用高亮查询"
- }
- },
- "highlight": {
- "fields":[
- "msg" : {}
- ]
- }
- }
highlight表示高亮,fields表示想要高亮的字段集合,msg是我们想要高亮的字段。
- 聚合查询
5.1分组统计
- // 返回统计结果
- {
- "aggs" : { //聚合操作
- "year_group" :{ //名称,可以随意取名
- "trems" : { //设置分组
- "field" : "year" //想要分组的字段
- }
- }
- },
- "size" : 0 //如果加上了就不会展示统计过后的源数据
- }
5.2 平均值统计
- // 返回统计结果
- {
- "aggs" : { //聚合操作
- "price_avg" :{ //名称,可以随意取名
- "avg" : { //设置平均值
- "field" : "price" //想要分组的字段
- }
- }
- },
- "size" : 0 //如果加上了就不会展示统计过后的源数据
- }
- 映射
1.概念与type
映射就相当于mysql当中创建的字段,官网上说的Elasticsearch 支持如下简单域类型:
JSON type |
域 type |
布尔型: true 或者 false |
boolean |
整数: 123 |
long |
浮点数: 123.45 |
double |
字符串,有效日期: 2014-09-15 |
date |
字符串: foo bar |
string |
简单类型:
- 字符串: string
- 整数 : byte, short, integer, long
- 浮点数: float, double
- 布尔型: boolean
- 日期: date
- 创建映射(mapping)
- PUT Http:127.0.0.1:9200/user/_mapping
- {
- "properties" : {
- "name" : { //字段名称
- "type" : "text", // text表示可以分词
- "index" : true //这个字段可以索引查询
- },
- "telephone_number" : {
- "type" : "keyword" // keyword表示不可以分词
- "index" : false //这个字段在文档中只做存储而不会创建倒排索引
- }
- }
创建名称为user的索引,并且给他设置字段映射_mapping。
- 查看映射
- GET Http:127.0.0.1:9200/user/_mapping
查看索引名称为user的映射结构。
- 分词器
1.自带的几种分词器
分词器 |
解释 |
standard |
标准标记器,标准过滤器,小写过滤器,停止过滤器 |
simple |
小写的分词器 |
stop |
小写标记器,停止过滤器 |
keyword |
不分词,内容整体作为一个值 |
whitespace |
以空格分词 |
language |
以语言分词 |
snowball |
标准标记器,标准过滤器,小写过滤器,停止过滤器,雪球过滤器 |
custom |
自定义分词。至少需要指定一个 Tokenizer, 零个或多个Token Filter, 零个或多个Char Filter |
pattern |
正则分词 |
- Java 客户端操作
1.基础配置
1.1 maven配置
依赖版本一定要对应ES的版本
- <!--spring-boot-elasticsearch依赖-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
- <version>7.6.1</version>
- </dependency>
- <!--elasticsearch高级api rest-high-level-->
- <dependency>
- <groupId>org.elasticsearch.client</groupId>
- <artifactId>elasticsearch-rest-high-level-client</artifactId>
- <version>7.6.1</version>
- </dependency>
1.2 连接池工具类
- import org.apache.http.HttpHost;
- import org.apache.http.auth.AuthScope;
- import org.apache.http.auth.UsernamePasswordCredentials;
- import org.apache.http.client.CredentialsProvider;
- import org.apache.http.impl.client.BasicCredentialsProvider;
- import org.elasticsearch.client.Node;
- import org.elasticsearch.client.RestClient;
- import org.elasticsearch.client.RestClientBuilder;
- import org.elasticsearch.client.RestHighLevelClient;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import java.util.ArrayList;
- import java.util.List;
- @Configuration
- public class ElasticsearchConfig {
- /** 协议 */
- @Value("${elasticsearch.schema:http}")
- private String schema;
- /** 集群地址,如果有多个用“,”隔开 */
- @Value("${elasticsearch.address}")
- private String address;
- /** 连接超时时间 */
- @Value("${elasticsearch.connectTimeout}")
- private int connectTimeout;
- /** Socket 连接超时时间 */
- @Value("${elasticsearch.socketTimeout}")
- private int socketTimeout;
- /** 获取连接的超时时间 */
- @Value("${elasticsearch.connectionRequestTimeout}")
- private int connectionRequestTimeout;
- /** 最大连接数 */
- @Value("${elasticsearch.maxConnectNum}")
- private int maxConnectNum;
- /** 最大路由连接数 */
- @Value("${elasticsearch.maxConnectPerRoute}")
- private int maxConnectPerRoute;
- /** 用户名 */
- @Value("${elasticsearch.user}")
- private String user;
- /** 用户名 */
- @Value("${elasticsearch.password}")
- private String password;
- @Bean(name = "restHighLevelClient")
- public RestHighLevelClient restHighLevelClient() {
- //设置用户名密码
- CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
- credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password));
- // 拆分地址
- List<HttpHost> hostLists = new ArrayList<>();
- String[] hostList = address.split(",");
- for (String addr : hostList) {
- String host = addr.split(":")[0];
- String port = addr.split(":")[1];
- hostLists.add(new HttpHost(host, Integer.parseInt(port), schema));
- }
- // 转换成 HttpHost 数组
- HttpHost[] httpHost = hostLists.toArray(new HttpHost[]{});
- // 构建连接对象
- RestClientBuilder builder = RestClient.builder(httpHost);
- // 定义监听器,节点出现故障会收到通知。
- builder.setFailureListener(new RestClient.FailureListener() {
- @Override
- public void onFailure(Node node) {
- super.onFailure(node);
- }
- });
- // 异步请求连接延时配置
- builder.setRequestConfigCallback(requestConfigBuilder -> {
- //连接超时时间
- requestConfigBuilder.setConnectTimeout(connectTimeout);
- //Socket 连接超时时间
- requestConfigBuilder.setSocketTimeout(socketTimeout);
- //获取连接的超时时间
- requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeout);
- return requestConfigBuilder;
- });
- // 异步的httpclient连接数配置
- builder.setHttpClientConfigCallback(httpClientBuilder -> {
- // 最大连接数
- httpClientBuilder.setMaxConnTotal(maxConnectNum);
- // 最大路由连接数
- httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
- // 赋予连接凭证
- httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
- return httpClientBuilder;
- });
- return new RestHighLevelClient(builder);
- }
- }
1.3 application.yml配置
对于集群连接,address采用逗号间隔
- elasticsearch:
- schema: http
- address: 127.0.0.1:9200,127.0.0.1:9500,
- connectTimeout: 5000
- socketTimeout: 5000
- connectionRequestTimeout: 5000
- maxConnectNum: 100
- maxConnectPerRoute: 100
- user:
- password:
- 创建索引
ES一个索引默认有 5 个主分片,每个主分片默认有 1 个副本分片,即创建一个索引默认会有 10 个分片。
- CreateIndexRequest request = new CreateIndexRequest(indexName);
- request.settings(Settings.builder()
- .put("index.number_of_shards", 5)
- .put("index.number_of_replicas", 1)
- );
- CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request,RequestOptions.DEFAULT);
- return createIndexResponse.isAcknowledged();
第一行代码创建——请求创建索引对象
第二至五行配置索引信息
第三行设置索引的分片数为5
第三行设置索引的副本数为1
第六至七行通过基础配置中的——1.2的工具类,发起索引请求,请求参数为构建好的索引对象、RequestOptions.DEFAULT(默认网络请求配置)
第八行获取执行的结果,true为成功,false为失败
- 删除索引
- //Delete请求头
- DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
- //客户端执行请求,并接受返回值
- AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);