Java进阶4-Elasticsearch

ES简介

https://www.elastic.co/cn/what-is/elasticsearch
全文搜索属于最常见的需求, 开源的 Elasticsearch 是目前全文搜索引擎的首选。
它可以快速地储存、 搜索和分析海量数据。 维基百科、 Stack Overflow、 Github 都采用它。
image.png
Elastic 的底层是开源库 Lucene。 但是, 你没法直接用 Lucene, 必须自己写代码去调用它的
接口。 Elastic 是 Lucene 的封装, 提供了 REST API 的操作接口, 开箱即用。
REST API: 天然的跨平台。
官方文档: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
官方中文: https://www.elastic.co/guide/cn/elasticsearch/guide/current/foreword_id.html
社区中文:
https://es.xiaoleilu.com/index.html
http://doc.codingdict.com/elasticsearch/0/

一、 基本概念

ElasticSearch 设计的理念就是分布式搜索引擎,底层其实还是基于 lucene 的。核心思想就是在多台机器上启动多个 ES 进程实例,组成了一个 ES 集群。
数据结构 index 类别大表-> type具体表 -> mapping表结构定义-> document 一行-> field一个字段的值

1、 Index索引

动词, 相当于 MySQL 中的 insert;
名词, 相当于 MySQL 中的 Database;

2、 Type类型(8新版本去掉)
在 Index(索引) 中, 可以定义一个或多个类型。
类似于 MySQL 中的 Table; 每一种类型的数据放在一起;

3、 Document文档
保存在某个索引(Index) 下, 某种类型(Type) 的一个数据(Document),文档是 JSON 格
式的, Document 就像是 MySQL 中的某个 Table 里面的内容;

4、 倒排索引机制

分词,评分,排序

image.png

二、Docker 安装 ES及组件

1、 下载镜像文件以及网络配置

# 系统配置及生效
vim /etc/profile
source /etc/profile

# 修改网路配置,固定ip
cd /etc/sysconfig/network-scripts/
https://blog.csdn.net/FoxBryant/article/details/50491312

docker pull elasticsearch:7.4.2 存储和检索数据
docker pull kibana:7.4.2 可视化检索数据

docker images 查看下载的镜像
free -m 查询主机内存

# linux统一安装目录:mydata/ ?

# 修改 linux 的 yum 源
1) 、 备份原 yum 源
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
2) 、 使用新 yum 源
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
3) 、 生成缓存
yum makecache

# 修改docker镜像源
docker默认的源为国外官方源,下载速度较慢,可改为国内源
编辑或新建配置文件 /etc/docker/daemon.json
{
    "registry-mirrors": ["https://registry.docker-cn.com","http://hub-mirror.c.163.com"],
    "live-restore": true
}
# 重新启动docker服务
systemctl restart docker

2、 创建docker ps实例

ElasticSearch

mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data
# 允许所有请求访问es
echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml

chmod -R 777 /mydata/elasticsearch/  #保证可读可写权限

# 暴露名称、暴露端口、设置运行方式、配置运行占有、设置文件映射、目标镜像
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2

# 设置开机自动重启
docker update elasticsearch --restart=always

docker start ps编号
docker logs  ps编号

# 关闭防火墙
systemctl stop firewalld.service
systemctl status firewalld.service
systemctl start firewalld.service

plugins以后再外面装好插件重启即可;特别注意:
-e ES_JAVA_OPTS="-Xms64m -Xmx256m" \ 测试环境下, 设置 ES 的初始内存和最大内存, 否则导
致过大启动不了ES。

docker命令格式:参数dockerhub网站

Kibana

# 暴露名称、暴露端口、绑定es地址
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.42.129:9200 -p 5601:5601 \
-d kibana:7.4.2

# 设置开机自动重启
docker update kibana --restart=always

注意:http://虚拟机的地址:9200 一定改为自己虚拟机的地址

问题:启动kibana出现iptables: No chain/target/match by that name
1 查看最新防火墙配置
iptables -L
2 重启Docker服务
service docker restart

Nginx

 随便启动一个 nginx 实例, 只是为了复制出配置
 docker run -p 80:80 --name nginx -d nginx:1.10
 将容器内的配置文件拷贝到当前目录: docker container cp nginx:/etc/nginx .
 别忘了后面的点
 修改文件名称: mv nginx conf 把这个 conf 移动到/mydata/nginx 下
 终止原容器: docker stop nginx
 执行命令删除原容器: docker rm $ContainerId
 创建新的 nginx; 执行以下命令
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10

docker update nginx --restart=always

 给 nginx 的 html 下面放的所有资源可以直接访问;

image.png

三、初步检索

https://www.elastic.co/guide/en/elasticsearch/reference/7.2/getting-started-search.html

1、_cat检索

GET /_cat/nodes: 查看所有节点
GET /_cat/health: 查看 es 健康状况
GET /_cat/master: 查看主节点
GET /_cat/indices: 查看所有索引 show databases;

2、新增文档POST&PUT

保存一个数据, 保存在哪个索引的哪个类型下, 指定用哪个唯一标识
PUT customer/external/1; 在 customer 索引下的 external 类型下保存 1 号数据为

PUT customer/external/1
{
"name": "John Doe"
}

PUT 和 POST 都可以,
POST 新增。 如果不指定 id, 会自动生成 id。 指定 id 就会修改这个数据, 并新增版本号
PUT 可以新增可以修改。 PUT 必须指定 id; 由于 PUT 需要指定 id, 我们一般都用来做修改
操作, 不指定 id 会报错。

3、查询文档GET

GET customer/external/1
结果:
{
"_index": "customer", //在哪个索引
"_type": "external", //在哪个类型
"_id": "1", //记录 id
"_version": 2, //版本号
"_seq_no": 1, //并发控制字段, 每次更新就会+1, 用来做乐观锁
"_primary_term": 1, //同上, 主分片重新分配, 如重启, 就会变化
"found": true,
"_source": { //真正的内容
"name": "John Doe"
}
}

更新携带,并发控制测试 ?if_seq_no=0&if_primary_term=1

4、更新文档POST&PUT

POST customer/external/1/_update
{
"doc":{
"name": "John Doew"
}
}

或者POST customer/external/1
{
"name": "John Doe2"
} 

或者PUT customer/external/1
{
"name": "John Doe"
}

不同: POST 操作会对比源文档数据, 如果相同不会有什么操作, 文档 version 不增加
PUT 操作总会将数据重新保存并增加 version 版本;
带_update 对比元数据如果一样就不进行任何操作。
看场景;
对于大并发更新, 不带 update;
对于大并发查询偶尔更新, 带 update; 对比更新, 重新计算分配规则。

更新同时增加属性
POST customer/external/1/_update
{
"doc": { "name": "Jane Doe", "age": 20 }
} 
PUT 和 POST 不带_update 也可以

5、删除文档DELETE

# 删除文档
DELETE customer/external/1 
# 删除索引
DELETE customer 

6、批量操作_bulk

POST customer/external/
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }

POST /_bulk
{ "delete": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "create": { "_index": "website", "_type": "blog", "_id": "123" }}
{ "title": "My first blog post" }
{ "index": { "_index": "website", "_type": "blog" }}
{ "title": "My second blog post" }
{ "update": { "_index": "website", "_type": "blog", "_id": "123"} }
{ "doc" : {"title" : "My updated blog post"} }

bulk API 以此按顺序执行所有的 action(动作) 。 如果一个单个的动作因任何原因而失败,
它将继续处理它后面剩余的动作。 当 bulk API 返回时, 它将提供每个动作的状态(与发送
的顺序相同),所以您可以检查是否一个指定的动作是不是失败了。

7、样本数据bank

我准备了一份顾客银行账户信息的虚构的 JSON 文档样本。 每个文档都有下列的 schema(模式) :

{
"account_number": 0,
"balance": 16623,
"firstname": "Bradshaw",
"lastname": "Mckenzie",
"age": 29,
"gender": "F",
"address": "244 Columbus Place",
"employer": "Euron",
"email": "bradshawmckenzie@euron.com",
"city": "Hobucken",
"state": "CO"
}

es样本数据切换到老版本才有:
https://github.com/elastic/elasticsearch/blob/v6.8.18/docs/src/test/resources/accounts.json
导入测试数据 POST bank/account/_bulk 测试数据

POST bank/account/_bulk
accounts.json数据

四、进阶检索

https://www.elastic.co/guide/en/elasticsearch/reference/7.2/search-search.html

1、 SearchAPI

ES 支持两种基本方式检索:
一个是通过使用 REST request URI 发送搜索参数(uri+检索参数)
另一个是通过使用 REST request body 来发送它们(uri+请求体)

# uri+检索参数
GET bank/_search?q=*&sort=account_number:asc

# uri+请求体
GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": "desc"
    },
    {
      "balance": "asc"
    }
  ]
}

检索_search结果分析:
image.png
HTTP 客户端工具( POSTMAN),get 请求不能携带请求体,我们变为 post 也是一样的
我们 POST 一个 JSON 风格的查询请求体到 _search API。
需要了解, 一旦搜索的结果被返回,Elasticsearch 就完成了这次请求,并且不会维护任何
服务端的资源或者结果的 cursor( 游标)

2、 Query DSL

1)基本语法格式

Elasticsearch 提供了一个可以执行查询的 Json 风格的 DSL(domain-specific language 领域特定语言)。称为 Query DSL。

  • 一个查询语句的典型结构

image.png

  • 如果是针对某个字段, 那么它的结构如下:

image.png

  • 查询所有,分页,排序,返回部分字段
# 查询所有,分页,排序,返回部分字段
GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 5,
  "_source": ["age","balance"]
}

image.png

2)返回部分字段

# _source选取字段
GET bank/_search
{
"query": {"match_all": {}
},
"from": 0,
"size": 5,
"_source": ["age","balance"]
}

3)match匹配查询

  • **基本类型( 非字符串),精确匹配 **
# 基本类型非字符串,精确匹配
# match 返回 account_number=20 的

GET bank/_search
{
  "query": {
    "match": {
      "account_number": "20"
    }
  }
}
  • 字符串, 全文检索
# 字符串, 全文检索
# 最终查询出 address 中包含 mill 单词的所有记录。match 当搜索字符串类型的时候, 会进行全文检索, 并且每条记录有相关性得分。

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  }
}
  • 字符串, 多个单词(分词+全文检索)
# 字符串, 多个单词(分词+全文检索)
# 最终查询出 address 中包含 mill 或者 road 或者 mill road 的所有记录, 并给出相关性得分

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill road"
    }
  }
}

4)match_phrase短语匹配

# match_phrase【 短语匹配】
# 将需要匹配的值当成一个整体单词( 不分词) 进行检索
# 查出 address 中包含 mill road 的所有记录, 并给出相关性得分

GET bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill road"
    }
  }
}

5)multi_match多字段匹配

# multi_match【 多字段匹配】
# state 或者 address 包含 mill

GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",
      "fields": [
        "state",
        "address"
      ]
    }
  }
}

6)bool 复合查询

bool 用来做复合查询:
复合语句可以合并 任何 其它查询语句, 包括复合语句, 了解这一点是很重要的。 这就意味着, 复合语句之间可以互相嵌套, 可以表达非常复杂的逻辑。

  • must: 必须达到 must 列举的所有条件
GET bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },{ "match": { "gender": "M" } }
]
}
}
}
  • should: 应该达到 should 列举的条件, 如果达到会增加相关文档的评分, 并不会改变查询的结果。 如果 query 中只有 should 且只有一种匹配规则, 那么 should 的条件就会被作为默认匹配条件而去改变查询结果。
GET bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "gender": "M" } }
],
"should": [
{"match": { "address": "lane" }}
]
}
}
}
  • must_not 必须不是指定的情况
# address 包含 mill, 并且 gender 是 M, 如果 address 里面有 lane 最好不过, 但是 email 必须不包含 baluba.com

GET bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "gender": "M" } }
],
"should": [
{"match": { "address": "lane" }}
],
"must_not": [
{"match": { "email": "baluba.com" }}
]
}
}

image.png

7)filter结果过滤

并不是所有的查询都需要产生分数, 特别是那些仅用于 “filtering”(过滤) 的文档。 为了不计算分数Elasticsearch 会自动检查场景并且优化查询的执行。

# 没用filter结果过滤,会计算得分
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "age": {
              "gte": 18,
              "lte": 30
            }
          }
        }
      ]
    }
  }
}

# 使用filter结果过滤,不会计算得分
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "filter": {
        "range": {
          "balance": {
            "gte": 10000,
            "lte": 20000
          }
        }
      }
    }
  }
}

8)term非text字段匹配

和 match 一样。匹配某个属性的值。 全文检索字段用 match, 其他非 text 字段匹配用 term。字段名.keyword精确匹配。
image.png

# term,全文检索字段用match,其他非text字段用term
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "age": {
              "value": "28"
            }
          }
        },
        {
          "match": {
            "address": "990 Mill Road"
          }
        }
      ]
    }
  }
}

# address.keyword精确匹配
GET bank/_search
{
  "query": {
    "match": {
      "address.keyword": "499"
    }
  }
}

9)aggregations执行聚合

聚合提供了从数据中分组和提取数据的能力。 最简单的聚合方法大致等于 SQL GROUP BY 和 SQL 聚合函数。 在 Elasticsearch 中, 您有执行搜索返回 hits( 命中结果) , 并且同时返回聚合结果, 把一个响应中的所有 hits( 命中结果) 分隔开的能力。 这是非常强大且有效的,您可以执行查询和多个聚合, 并且在一次使用中得到各自的( 任何一个的) 返回结果, 使用一次简洁和简化的 API 来避免网络往返。

  • **搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄, 但不显示这些人的详情。 **
# 搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄, 但不显示这些人的详情。
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "age"
      }
    },
    "avg_age": {
      "avg": {
        "field": "age"
      }
    }
  },
  "size": 0
}

条件解释:
image.png

  • 按照年龄聚合, 并且请求这些年龄段的这些人的平均薪资
# 按照年龄聚合, 并且请求这些年龄段的这些人的平均薪资
GET bank/account/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "age_avg": {
      "terms": {
        "field": "age",
        "size": 1000
      },
      "aggs": {
        "banlances_avg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 1000
}
  • **查出所有年龄分布, 并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄段的总体平均薪资 **
# 查出所有年龄分布, 并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄段的总体平均薪资
GET bank/account/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "age_agg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "gender_agg": {
          "terms": {
            "field": "gender.keyword",
            "size": 100
          },
          "aggs": {
            "balance_avg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "balance_avg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 1000
}

**
**

3、 Mapping

1)字段类型

image.png
image.png
image.png
image.png

2)映射

Mapping(映射)
Mapping 是用来定义一个文档( document), 以及它所包含的属性( field) 是如何存储和索引的。 比如, 使用 mapping 来定义:

  • 哪些字符串属性应该被看做全文本属性(full text fields)
  • 哪些属性包含数字, 日期或者地理位置
  • 文档中的所有属性是否都能被索引(_all 配置)
  • 日期的格式
  • 自定义映射规则来执行动态添加属性
  • 查看 mapping 信息: GET bank/_mapping
  • 修改 mapping 信息:自动猜测的映射类型
    image.png

3)新版本改变

Es7 及以上移除了 type 的概念。

  • 关系型数据库中两个数据表示是独立的, 即使他们里面有相同名称的列也不影响使用,
    但 ES 中不是这样的。 elasticsearch 是基于 Lucene 开发的搜索引擎, 而 ES 中不同 type
    下名称相同的 filed 最终在 Lucene 中的处理方式是一样的。
  • 两个不同 type 下的两个 user_name, 在 ES 同一个索引下其实被认为是同一个 filed,
    你必须在两个不同的 type 中定义相同的 filed 映射。 否则, 不同 type 中的相同字段
    名称就会在处理中出现冲突的情况, 导致 Lucene 处理效率下降。
  • 去掉 type 就是为了提高 ES 处理数据的效率。

Elasticsearch 7.x

  • URL 中的 type 参数为可选。 比如, 索引一个文档不再要求提供文档类型。
    Elasticsearch 8.x
  • 不再支持 URL 中的 type 参数。
    解决:
    1)将索引从多类型迁移到单类型, 每种类型文档一个独立索引
    2)将已存在的索引下的类型数据, 全部迁移到指定位置即可。 详见数据迁移

查看映射

# 查看索引的文档映射
GET /bank/_mapping
GET /bank/_search

创建映射

# 创建索引并指定映射
PUT /my-index
{
  "mappings": {
    "properties": {
      "age":    { "type": "integer" },  
      "email":  { "type": "keyword"  }, 
      "name":   { "type": "text"  }     
    }
  }
}

添加新的字段映射

# 添加新的字段映射 index:false等于字段不参与索引
PUT /my-index/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false
    }
  }
}

**** 更新映射**
对于已经存在的映射字段, 我们不能更新。 更新必须创建新的索引进行数据迁移

数据迁移

#先创建出 new_twitter 的正确映射。 然后使用如下方式进行数据迁移
PUT /newbank
{
  "mappings": {
    "properties": {
      "account_number": {
        "type": "long"
      },
      "address": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "balance": {
        "type": "long"
      },
      "city": {
        "type": "keyword"
      },
      "email": {
        "type": "keyword"
      },
      "employer": {
        "type": "keyword"
      },
      "firstname": {
        "type": "text"
      },
      "gender": {
        "type": "keyword"
      },
      "lastname": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "state": {
        "type": "keyword"
      }
    }
  }
}

# 查看新建的数据迁移
GET /newbank/_mapping

# 将旧索引的 type 下的数据进行迁移
POST _reindex
{
  "source": {
    "index": "bank",
    "type": "account"
  },
  "dest": {
    "index": "newbank"
  }
}

# 查看迁移后的索引newbank数据
GET /newbank/_search

# Es7及以上移除了type的概念。Elasticsearch8不支持
# 老的数据有迁移方案_reindex

4、 分词

一个 tokenizer( 分词器) 接收一个字符流, 将之分割为独立的 tokens( 词元, 通常是独立的单词) , 然后输出 tokens 流。
例如, whitespace tokenizer 遇到空白字符时分割文本。 它会将文本 “Quick brown fox!” 分割为 [Quick, brown, fox!]。
该 tokenizer(分词器) 还负责记录各个 term(词条) 的顺序或 position 位置(用于 phrase 短语和 word proximity 词近邻查询) , 以及 term(词条) 所代表的原始 word(单词) 的 start(起始) 和 end(结束) 的 character offsets(字符偏移量) (用于高亮显示搜索的内容) 。Elasticsearch 提供了很多内置的分词器, 可以用来构建 custom analyzers(自定义分词器) 。

安装 ik 分词器

# 注意: 不能用默认 elasticsearch-plugin install xxx.zip 进行自动安装
https://github.com/medcl/elasticsearch-analysis-ik/releases?after=v7.4.2 对应 es 版本安装

# 进入 es 容器内部 plugins 目录
docker exec -it 容器 id /bin/bash
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-anal
ysis-ik-7.4.2.zip

# 在plugins目录
unzip 下载的文件
rm –rf *.zip
mv elasticsearch/ ik

# 文件权限rwx
chmod -R 777 ik/
drwxrwxrwx. 3 root root 243 Nov  2 00:03 ik

# 可以确认是否安装好了分词器
cd ../bin
elasticsearch plugin list: # 即可列出系统的分词器

测试分词器_analyze

# 使用默认
POST _analyze
{
"text": "我是中国人"
}

# 使用分词器
POST _analyze
{ "analyzer": "ik_smart",
"text": "我是中国人"
}

# 另外一个分词器
POST _analyze
{ "analyzer": "ik_max_word",
"text": "我是中国人"
}

能够看出不同的分词器, 分词有明显的区别, 所以定义一个索引不能再使用默认的 mapping 了, 
要手工建立 mapping, 因为要选择分词器。

自定义词库IK

需要提前安装nginx,并测试请求响应index.html。按照标红的路径利用 nginx 发布静态资源,按照请求路径, 创建对应的文件夹以及文件, 放在nginx 的 html 下。

修改/usr/share/elasticsearch/plugins/ik/config/中的 IKAnalyzer.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 修改处 -->
<entry key="remote_ext_dict">http://192.168.128.130/fenci/myword.txt</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
# 自定义分词txt测试
POST _analyze
{ "analyzer": "ik_smart",
"text": "乔碧萝殿下"
}

更新完成后, es 只会对新增的数据用新词分词。 历史数据是不会重新分词的。 如果想要历史数据重新分词。 需要执行:POST my_index/_update_by_query?conflicts=proceed

五、 Elasticsearch-Rest-Client

**1)、9300: TCP
** spring-data-elasticsearch:transport-api.jar;
 springboot 版本不同, transport-api.jar 不同, 不能适配 es 版本
 7.x 已经不建议使用, 8 以后就要废弃

**2)、9200: HTTP
** JestClient: 非官方, 更新慢
 RestTemplate: 模拟发 HTTP 请求, ES 很多操作需要自己封装, 麻烦
 HttpClient: 同上
 Elasticsearch-Rest-Client: 官方 RestClient, 封装了 ES 操作, API 层次分明, 上手简单
最终选择 Elasticsearch-Rest-Client(elasticsearch-rest-high-level-client)
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.4/java-rest-high.html

image.png

1、SpringBoot 整合

<dependency>
  <groupId>org.elasticsearch.client</groupId>
  <artifactId>elasticsearch-rest-high-level-client</artifactId>
  <version>7.4.2</version>
</dependency>

2、配置

@Bean
    RestHighLevelClient client() {
        RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.56.10", 9200,
                                                                    "http"));
        return new RestHighLevelClient(builder);
    }

3、使用

@Test
    void test1() throws IOException {
        Product product = new Product();
product.setSpuName("华为");
product.setId(10L);
IndexRequest request = new IndexRequest("product").id("20")
    .source("spuName","华为","id",20L);
try {
    IndexResponse response = client.index(request, RequestOptions.DEFAULT);
    System.out.println(request.toString());IndexResponse response2 = client.index(request, RequestOptions.DEFAULT);
} catch (ElasticsearchException e) {
    if (e.status() == RestStatus.CONFLICT) {
    }
}
}
手把手视频详细讲解项目开发全过程,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 优势亮点(简化) 本次课程以SpringData为中心,重点讲解了其JPA组件,扩展讲解了redis,mongDB,ES组件,并且对部分组件做了必要的源码分析。而且在课程的最后部分加入了一个综合案例,可以将前面章节所学知识点应用到一个项目中,帮助学生理解消化。 配图(持久层技术,无界面) 课程主要内容 第一章 SpringData概述 1.持久层开发的问题 2.SpringData简介 第二章 JPA回顾 1.JPA基础 2.JPA实战 3.JPA的重要API介绍 第三章 SpringData JPA基础 1.SpringData JPA简介 2.SpringData JPA快速入门 3.SpringData Jpa运行原理分析 第四章 SpringData JPA的多种查询方式 1.父接口方法查询 2.方法命名规则查询 3.JPQL查询 4.本地SQL查询 5.Specifications动态查询 第五章 SpringData JPA实现多表操作 1.多表关系分析 2.案例表间关系 3.一对一关系 4.一对多关系 5.多对多关系 第六章 SpringData Redis 1.SpringData Redis简介 2.Redis环境搭建 3.SpringData Redis入门案例 4.SpringData Redis的序列化器 5.SpringData Redis运行原理分析 6.SpringData Redis常见操作 第七章 Repository和Template的选用 第八章 SpringData ElasticSearch 1.SpringData ElasticSearch简介 2.ElasticSearch环境搭建 3.ElasticSearch基础知识回顾 4.SpringData ElasticSearch入门案例 5.SpringData ElasticSearch实现CRUD操作 第九章 SpringData MongDB 1.SpringData MongDB简介 2.MongDB环境搭建 3.MongDB基础知识回顾 4.SpringData MongDB入门案例 5.SpringData MongDB实现CRUD操作 第十章 综合案例 1.案例说明及思路分析 2.代码实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页
评论

打赏作者

程序员星云

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值