目录
1.简单介绍🚗🚗🚗
Elaticsearch,简称为ES, ES是一个开源的高扩展的分布式全文搜索引擎,是整个ElasticStack技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。
官方地址:来这哈
2.安装与下载🚗🚗🚗
- 1.docker pull elasticsearch:7.4.2
在docker中使用命令拉取镜像,安装到docker
- 2.docker pull kibana:7.4.2
安装es可视化工具
安装需要时间,莫着急哦~
3.安装启动es🚗🚗🚗
- 1.创建挂载目录
mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticssearch/data
- 2.设置允许远程访问
echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml
- 3.给文件赋权限
给elasticsearch下全部文件赋可读可写可执行的权限
chomd -R 777 /mydata/elasticsearch/
- 4..启动elasticsearch
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx128m" -v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/elasticsearch.yml -v /mydata/elasticsearch/data:/usr/share/elasticsearch/data -v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins -d elasticsearch:7.4.2
- --name : 容器名字
- -p: 暴露端口、9200:访问端口,9300:做集群时内部暴露端口
- -e "discovery.type=single-node" : 单机启动
- -e ES_JAVA_OPTS="-Xms64m -Xmx128m" : 初始64m,最大128m
- -v: 将容器中的文件挂在到自己的机器上
- -d: 启动镜像的名称
5.访问
端口
4.安装启动kibana 🚗🚗🚗
- 1.查看docker对外暴露的ip
docker inspect elasticsearch | grep IPAddress
- 2.启动kibana
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://刚刚查出来的docker暴露的ip:9200 -p 5601:5601 -d kibana:7.4.2
ELASTICSEARCH_HOSTS= “不是自己的Linux上的ip地址,而是步骤一查出来docker地址”
- 3.访问
5.初步检索 🚗🚗🚗
5.1_cat
使用postman发送请求~,使用自己虚拟机的IP地址!!!全部为GET请求
- 1.查看所有节点信息 /_cat/nodes
http://192.168.20.130:9200/_cat/nodes
- 2.查看es健康状况 /_cat/health
http://192.168.20.130:9200/_cat/health
- 3.查看主页节点 /_cat/master
http://192.168.20.130:9200/_cat/master
- 4.查看所有索引 /_cat/indices
http://192.168.20.130:9200/_cat/indices
5.2索引一个文档(保存)
保存一个数据,保存在哪个索引的那个类型下指定用哪个唯一标识
- 1.使用命令保存一条记录(put/post请求、发送json)
http://192.168.20.130:9200/customer/external/1
注:
- 1.同一个请求,发送多次,就变为修改~
- 2.POST新增。如果不指定id,会自动生成id。指定id 就会修改这个数据,并新增版本号
- 3.PUT可以新增可以修改。PUT必须指定id;由于PUT需要指定id,我们一般都用来做修操作,不指定id会报错。
5.3查询文档
- 1.发送get请求查询 customer/external/
http://192.168.20.130:9200/customer/external/1
5.4更新一个文档
发送PSOT请求,指定哪个索引下,哪个类型下,id的是多少
- 1.post携带update
会对比原来的数据,如果更新前后一致,则不做改变。
http://192.168.20.130:9200/customer/external/1/_update
- 2.post不携带update
不会对比原来的数据,直接叠加版本
http://192.168.20.130:9200/customer/external/1
- 3.put
和post不懈怠update一样,put可以新增也可以修改,但必须指定id
http://192.168.20.130:9200/customer/external/1
5.5删除
发送delete请求,删除那个索引、那个类型下的id
- 1.删除某一条数据
http://192.168.20.130:9200/customer/external/1
- 2.删除整个索引
http://192.168.20.130:9200/customer
5.6bulk批量api
- 1.使用kibana批量发送
- 2.es测试数据
测试数据放到资源那里了,自行下载
6.进阶检索🚗🚗🚗
6.1基本检索方式
- 1.第一种检索:检索条件直接写在路径后面
GET bank/_search?q=*&sort=account_number:asc
- 2.第二种检索:使用请求体
使用Query DSL,提供一个可执行的Json风格的DSL
GET bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"balance": {
"order": "desc"
}
}
],
"from": 0,
"size": 5,
"_source": [
"balance",
"firstname"
]
}
query:代表查询条件
sort:代表排序条件
from: 从第几条数据开始查
size:每次查出多少条数据
_source:指定命中的字段
6.2基本语法
- 1.match【模糊查询】
模糊检索
GET bank/_search
{
"query": {
"match": {
"address": "kings"
}
}
}
- 2.match_phrase【字段查询】
指定上相应的字段和对应的值,进行精确查询
GET bank/_search
{
"query": {
"match_phrase": {
"address": "kings"
}
}
}
- 3.multi_match【多字段查询】
多字段匹配,fileds里的字段,只要有一个匹配query的值即可,而且还是分词查
GET bank/_search
{
"query": {
"multi_match": {
"query": "mill",
"fields": ["address","city"]
}
}
}
- 4.bool 【复合查询】
must: 必须匹配
must_not: 不能匹配
should:匹不匹配都可以
GET bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"gender": "M"
}
},
{
"match": {
"address": "mill"
}
}
],
"must_not": [
{
"match": {
"age": "28"
}
}
],
"should": [
{"match": {
"lastname": "wallace"
}}
]
}
}
}
- 4.filter【结果过滤】
不计算相关性得分
GET bank/_search
{
"query": {
"bool": {
"filter": {
"range": {
"age": {
"gte": 18,
"lte": 30
}
}
}
}
}
}
- 5.term
term是代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词拆解。
GET bank/_search
{
"query": {
"term": {
"age":28
}
}
}
- 6.aggregations【执行聚合】
- 聚合提供了从数据中分组和提取数据的能力。
- 最简单的聚合方法大致等于SQLGROUPBY和SQL聚合函数。
- 在Elasticsearch中,您有执行搜索返回hits (命中结果) ,并且同时返回聚合结果,把一个响应中的所有hits (命中结果)分隔开的能力。这是非常强大且有效的,您可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用一次简洁和简化的API来避免网络往返。
GET bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 10
}
},
"ageAvg":{
"avg": {
"field": "age"
}
},
"balanceAvg":{
"sum": {
"field": "balance"
}
}
},
"size": 0
}
aggs:使用聚合函数,名称要见名知意
avg:表示平均值
sum:表示求和
查出所有年龄分布,并且这些年龄段中M的平均薪资和F的平均薪资以及这个年龄段总体平均薪资
GET bank/_search
{
"query": {
"match_all": {}
},
"aggs": {
"ageAgg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"genderAgg": {
"terms": {
"field": "gender.keyword",
"size": 10
},"aggs": {
"balanceAvg": {
"avg": {
"field": "balance"
}
}
}
},
"ageBalance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
子聚合,在一个聚合函数名称下,在使用aggs聚合
6.3Mapping
- 1.创建映射
在创建索引时,规定字段的类型
PUT /my_index
{
"mappings": {
"properties": {
"age": {"type": "integer"},
"email": {"type": "keyword"},
"name": {"type": "text"}
}
}
}
- 2.添加新的字段映射
PUT /my_index/_mapping
{
"properties":{
"employee-id":{
"type": "keyword",
"index": false
}
}
}
- 3.更新映射
对于已经存在的映射字段,我们不能更新。更新必须创建新的索引进行数据迁移
- 4.数据迁移
先创建出新的正确映射,然后再迁移
POST _reindex
{
"source": {
"index": "bank",
"type": "account"
},
"dest": {
"index": "newbank"
}
}
source:原数据
dest:要迁移的数据
index:要迁移数据的名称
type:迁移数据的类型
6.4分词
- 一个tokenizer (分词器)接收一个字符流,将之分割为独立的tokens (词元,通常是独立的单词),然后输出 tokens 流。
- 例如, whitespace tokenizer 遇到空白字符时分割文本。它会将文本"Quick brown fox!" 分割为[Ouick, brown, fox]
- 1.安装ik分词器
官网:ik分词器
解压到elasticsearch的plugins下~ ,记得重启elasticsearch!!
- 2.测试分词效果
- 3.自定义分词
3.1使用nginx配置分词,再nginx的html下创建文件夹es,并配置location
3.2配置分词器地址
在ik分词器的配置文件中,添加分词器地址
重启elastic search~
7.Elasticsearch整合 🚗🚗🚗
7.1创建服务
在父工程下创建新模块作为检索服务,并导入依赖
<!--导入es的rest-high-level-client-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
但是如果<elasticsearch.version>7.4.2</elasticsearch.version>不生效,jar包冲突,版本不匹配,将版本不匹配的移除,重新引入!!!
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
<exclusion>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.4.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.4.2</version>
</dependency>
7.2写配置
编写配置类,被容器中注入RestHighLevelClient,并写入预检请求
@Configuration
public class ElasticSearchConfig {
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
COMMON_OPTIONS = builder.build();
}
@Bean
public RestHighLevelClient esRestClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("192.168.20.130", 9200, "http")
)
);
return client;
}
}
7.3测试
- 1.测试保存请求,也可修改
@Test
public void indexData() throws IOException {
IndexRequest indexRequest = new IndexRequest("users");
indexRequest.id("1");
//推荐方式,将对象转换为json
User user = new User();
user.setUserName("会敲代码的小张");
user.setAge(18);
user.setGender("男");
String jsonString = JSON.toJSONString(user);
indexRequest.source(jsonString, XContentType.JSON);
//执行保存
IndexResponse index = restHighLevelClient.index(indexRequest, ElasticSearchConfig.COMMON_OPTIONS);
//提取有用的数据
System.out.println(index);
}
@Data
class User{
private String userName;
private String gender;
private Integer age;
}
- 2.复查检索
@Test
public void select() throws IOException {
//1.创建检索请求
SearchRequest searchRequest = new SearchRequest();
//2.指定索引
searchRequest.indices("bank");
//3.指定DSL检索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//3.1构造query条件
sourceBuilder.query(QueryBuilders.matchQuery("address", "mill"));
//3.2构造聚合条件
//3.2.1-按照你啊年龄聚合
TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
sourceBuilder.aggregation(ageAgg);
//3.2.2-计算平均薪资
AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
sourceBuilder.aggregation(balanceAvg);
System.out.println("检索条件" + sourceBuilder.toString());
searchRequest.source(sourceBuilder);
//4.执行检索
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);
//5.分析结果
System.out.println("查询结果" + searchResponse.toString());
//5.1获取查到的所有数据
SearchHits hits = searchResponse.getHits();
//5.2查询真正的命中记录
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
String sourceAsString = hit.getSourceAsString();
Account account = JSON.parseObject(sourceAsString, Account.class);
System.out.println("值:" + account);
}
//5.3获取分析信息
Aggregations aggregations = searchResponse.getAggregations();
Terms ageAgg1 = aggregations.get("ageAgg");
for (Terms.Bucket bucket : ageAgg1.getBuckets()) {
String keyAsString = bucket.getKeyAsString();
System.out.println("年龄:"+keyAsString+"===>"+bucket.getDocCount());
}
Avg balanceAvg1 = aggregations.get("balanceAvg");
System.out.println("平均薪资:"+balanceAvg1.getValue());
}