Elasticsearch入门以及整合springboot

ElasticSearch

文章目录

  • ElasticSearch
    • 1. 基本概念
    • 2. 安装(采用docker安装)
    • 3. 初步检索
        • 3.1 索引一个文档
        • 3.2 查看文档
        • 3.3 更新文档
        • 3.4 删除
        • 3.4 bulk批量API
    • 4. 进阶检索
        • 4.1 SearchAPI
        • 4.2 Query DSL
          • 4.2.1 match_all
          • 4.2.2 match
          • 4.2.3 match_phrase
          • 4.2.4 multi_match
          • 4.2.5 bool
          • 4.2.6 filter
          • 4.2.7 term
          • 4.2.8 keyword
          • 4.2.8 aggregations
        • 4.3 Mapping
          • 4.3.1 创建映射
          • 4.3.2 添加新的字段映射
          • 4.3.3 更新映射
          • 4.3.4 数据迁移
        • 4.4 分词
          • 4.4.1 安装ik分词器
          • 4.4.2 自定义分词库
    • 5. Springboot整合
    • 扩展

底层是开源库 Lucene。Elastic是对Lucene的封装, 提供了REST API的操作接口

开源的Elasticsearch是目前全文搜索引擎的首选。它可以快速地存储、搜索和分析海量数据

官方文档

1. 基本概念

1、Index (索引)

动词,相当于MySQL中的insert

名词,相当于MySQL中的Database

2、Type (类型)

在Index(索引)中,可以定义一个或多个类型。

类似于MySQL中的Table,每一种类型的数据放在一起

3、Document(文档)

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

Elasticsearch入门以及整合springboot_第1张图片

4、倒排索引机制

Elasticsearch入门以及整合springboot_第2张图片

2. 安装(采用docker安装)

# 安装elasticsearch
docker pull elasticsearch:7.4.2

# 安装kibana(可视化)
docker pull kibana:7.4.2

# 创建外部目录 将es数据挂载出来
mkdir -p /Users/jinchengming/mydata/elasticsearch/config        
mkdir -p /Users/jinchengming/mydata/elasticsearch/data  
# es配置文件 即将来外部任何机器都可以访问
echo "http.host: 0.0.0.0">>/Users/jinchengming/mydata/elasticsearch/config/elasticsearch.yml

# 启动 elasticsearch
# 9200 外部访问api的端口 9300集群部署时 节点间通信端口
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" -v /Users/jinchengming/mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /Users/jinchengming/mydata/elasticsearch/data:/usr/share/elasticsearch/data -v /Users/jinchengming/mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins -d elasticsearch:7.4.2

测试是否启动成功
Elasticsearch入门以及整合springboot_第3张图片

简单命令

# 返回的所有节点 如果是集群部署 前面带* 表示当前节点是主节点
# localhost:9200/_cat/nodes
127.0.0.1 50 94 1 0.22 0.08 0.06 dilm * fa09e7661fc2
# 查看es健康状况
# localhost:9200/_cat/health
# 查看主节点
# localhost:9200/_cat/master
# 查看所有索引
# localhost:9200/_cat/indices
# 启动kibana
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://127.0.0.1:9200 -p 5601:5601 -d kibana:7.4.2 
# 经过测试 网络不通 日志输出访问不到127.0.1的es服务
# 通过指定容器内ip
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://172.17.0.3:9200 -p 5601:5601 -d kibana:7.4.2 
# 查看容器内ip
jinchengming@MacBook-Pro elasticsearch % docker inspect --format='{{.Name}} - {{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
/kibana - 172.17.0.4
/elasticsearch - 172.17.0.3
/rabbitmq3.7.7 - 172.17.0.2
/mysql01 - 172.17.0.2
/mongodb - 172.17.0.3

成功访问

Elasticsearch入门以及整合springboot_第4张图片

汉化

进入容器后 ,编辑/usr/local/kibana/config文件夹下的kibana.yml文件,新增下面这个配置

i18n.locale: "zh-CN"

然后重启服务即可
Elasticsearch入门以及整合springboot_第5张图片

3. 初步检索

3.1 索引一个文档

语法:请求方式:PUT

案例中的请求表示在customer索引下的external类型下保存一号数据 ,数据在请求体中,是个json
Elasticsearch入门以及整合springboot_第6张图片

相同的id 再保存一次就是更新操作,result由created变为updated,version加1
Elasticsearch入门以及整合springboot_第7张图片

关于请求方式

PUT 和 POST都可以

POST新增。如果不指定id,会自动生成id。指定id就会修改这个数据,并新增版本号

PUT可以新增可以修改,PUT必须指定id,由于PUT需要指定id,我们一般都用来做修改操作,不指定id会报错。

3.2 查看文档

GET customer/external/1

返回值:

{
    "_index": "customer", // 索引 
    "_type": "external",  // 类型
    "_id": "1",						// id
    "_version": 2,				// 版本
    "_seq_no": 1,					// 并发控制字段,每次更新就会+1,用来做乐观锁
    "_primary_term": 1,		// 同上,主分片重新分配,如重启,就会变化
    "found": true,				// 是否查询到数据
    "_source": {					// 数据内容
        "name": "chengming"
    }
}

3.3 更新文档

除了上面的POST和PUT带上id可以更新文档外,还可以直接请求上用_update表示更新操作,数据要加上doc将数据包起来
Elasticsearch入门以及整合springboot_第8张图片

区别:_update操作更新是会检查数据,如果数据和原数据相同 ,则version和_seq_no都不会增加

3.4 删除

删除指定文档
Elasticsearch入门以及整合springboot_第9张图片

删除索引
Elasticsearch入门以及整合springboot_第10张图片

elasticsearch中没有删除类型的操作

3.4 bulk批量API

请求中使用_bulk表示批量,请求体中两行为一条数据,第一行为操作类型和条件,第二行为数据

批量新增数据

`postman不方便测试这种操作,采用kibana测试

Elasticsearch入门以及整合springboot_第11张图片

可以看出右边的items是对每一条数据新增的单独统计,所以不同于mysql的批量更新,没有事务,每个操作是独立的

Elasticsearch入门以及整合springboot_第12张图片

导入官网提供的测试数据

测试数据下载地址

Elasticsearch入门以及整合springboot_第13张图片

成功导入后,查看当前es中所有索引,可以看出刚才导入成功1000条数据
Elasticsearch入门以及整合springboot_第14张图片

4. 进阶检索

ES支持两种基本方式检索:

  • 一个是通过使用 REST request URI 发送搜索参数(URI + 检索参数)
  • 另一个是通过使用 REST request body 来发送它们(URI + 请求体)

4.1 SearchAPI

uri+检索参数

# 查询bank索引下所有(*)数据,并按照account_number升序 
GET bank/_search?q=*&sort=account_number:asc

查询结果:

{
  "took" : 30, // 查询时间 :毫秒
  "timed_out" : false, // 是否超时
  "_shards" : { // 集群相关
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1000,
      "relation" : "eq"
    },
    "max_score" : null, // 得分 查询全部 不存在分数
    "hits" : [   // 命中的记录
      {
        "_index" : "bank",
        "_type" : "account",
        "_id" : "0",
        "_score" : null,
        "_source" : { // 数据源信息
          "account_number" : 0,
          "balance" : 16623,
          "firstname" : "Bradshaw",
          "lastname" : "Mckenzie",
          "age" : 29,
          "gender" : "F",
          "address" : "244 Columbus Place",
          "employer" : "Euron",
          "email" : "[email protected]",
          "city" : "Hobucken",
          "state" : "CO"
        },
        "sort" : [
          0
        ]
      },
      ...
      ...
      ...
      ]

4.2 Query DSL

uri+请求体

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": "asc"
    },
    {
      "balance": "desc"
    }
  ],
  // 相当于分页操作
  "from": 10, 
  "size": 10,
  "_source": ["balance","account_number"] // 指定返回字段
}

上面案例中的排序规则是简写,完整写法如下

4.2.1 match_all

匹配所有

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "balance": {
        "order": "desc" // 针对balance降序排列
      }
    }
  ]
}
4.2.2 match

全文检索,会对检索条件进行分词匹配,按照倒排索引机制排序

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill lane"
    }
  }
}
4.2.3 match_phrase

短语匹配,将需要匹配的值当成一个整体单词(不分词)进行检索

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

此时返回结果只有一条"address" : "198 Mill Lane"的数据,而match返回多条。

4.2.4 multi_match

多字段匹配

GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",
      "fields": ["state","address"] // 在state或者address中包含mill
    }
  }
}
4.2.5 bool

复合查询

GET bank/_search
{
  "query": {
    "bool": {	// 复合查询
      "must": [  // 必须满足
        {
          "match": {
            "gender": "M"
          }
        },
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "must_not": [ // 必须不满足
        {
          "match": {
            "age": 18
          }
        }
      ],
      "should": [ // 应该满足,即如果满足,得分高
        {"match": {
          "lastname": "Wallace"
        }}
      ]
    }
  }
}
4.2.6 filter

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

即,filter过滤不会贡献分数,仅过滤

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        }
      ],
      "filter": {
        "range": {
          "balance": {
            "gte": 10000,
            "lte": 20000
          }
        }
      }
    }
  }
}
4.2.7 term

和match一样,匹配某个属性的值,全文检索字段用match,其他非text字段匹配用term

GET bank/_search
{
  "query": {
    "term": {
      "age": {
        "value": 20
      }
    }
  }
}

如果是地址这种(文本字段)需要检索的,用match 但是年龄(非文本字段)这种需要精确匹配的建议用term

4.2.8 keyword

使用match时,如果需要精确匹配,可以使用.keyword

GET bank/_search
{
  "query": {
    "match": {
      "address.keyword":"789 Madison Street"
    }
  }
}

feild.keyword不同于match_phrase,前者精确匹配,后者为短语匹配,只是不分词而且

4.2.8 aggregations

执行聚合,聚合提供了从数据中分组和提取数据的能力。最简单的聚合方法大致等于 SQL GROUP BYSQL 聚合函数。

在ES中,有执行搜索返回的hits(命中结果),并且同时返回聚合结果。

把一个响应中的所有命中分割开的能力,这是非常强大且有效的,可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用一次简洁和简化的API来避免网络往返。

# 搜索address中包含mill的所有人的年龄分布以及平均年龄、平均工资
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "size": 0,   // 不显示搜索数据
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 10
      }
    },
    "ageAvg":{
      "avg": {
        "field": "age"
      }
    },
    "balanceAvg":{
      "avg": {
        "field": "balance"
      }
    }
  }
}

返回结果:

处理匹配返回的hits外,还返回了 aggregations信息

Elasticsearch入门以及整合springboot_第15张图片
聚合结果中再使用聚合,即子聚合

如:返回的年龄分布中,再求个年龄的平均工资

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "balanceAvg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

返回结果:

升级:上述分布结果中,再分布求出男和女的平均工资

在对gender(文本字段)进行聚合时,必须使用精确匹配,即使用keyword

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "genderAgg": {
          "terms": {
            "field": "gender.keyword"
          },
          "aggs": {
            "genderBalanceAvg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "balanceAvg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

4.3 Mapping

4.3.1 创建映射
# 创建索引时指定映射
PUT /my_index
{
  "mappings": {
    "properties": {
      "age":{"type": "integer"},
      "email":{"type": "keyword"}, // 只能精确匹配
      "name":{"type": "text"}, // 会分词检索
    }
  }
}
4.3.2 添加新的字段映射
PUT /my_index/_mapping
{
  "properties": {
      "employee-id":{
        "type": "long",
        "index":false // 创建和添加时,默认都是true,表示当前字段是否参与检索
      }
    }
}
4.3.3 更新映射

对于已存在的映射字段,不可以修改type,如果一定要改,只能创建新的索引,然后进行数据迁移

4.3.4 数据迁移
# 建立新的索引
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"
      }
    }
  }
}
# 数据迁移
POST _reindex
{
  "source": {
    "index": "bank",
    "type": "account"  // 如果这个索引存在type,需要指定 (6.0版本后放弃type)
  },
  "dest": {
    "index": "newbank"
  }
}

4.4 分词

一个tokenizer(分词器)接收一个字符流,将之分割为独立的tokens(词元,通常是独立的单词),然后输出tokens流。

例如:whitespace tokenizer遇到空白字符时分割文本。它会将文本“Quick brown fox!”分割为[Quick,brown,fox!]

tokenizer(分词器)还负责记录各个term(词条)的顺序或position位置(用于phrase短语和word proximity词近邻查询),以及term(词条)所代表的原始word(单词)的start(起始)和end(结束)的character offsets(字符偏移量) (用于高亮显示搜索的内容)。

ES 提供了很多内置的分词器,可以用来构建custom analyzers (自定义分词器)

POST _analyze
{
  "analyzer": "standard", // 标准分词器
  "text": "I love you"
}

内置的分词器都是支持英文分词的,要支持中文分词,需要安装自己的分词器,一般使用开源的ik分词器

4.4.1 安装ik分词器

github地址

安装踩坑(mac下安装的):

"Caused by: java.nio.file.FileSystemException: /usr/share/elasticsearch/plugins/.DS_Store/plugin-descriptor.properties: Not a directory",

这应该是开发者的锅,他们在gitignore中没有包括.DS_Store ,找到.DS_Store文件,删掉重启就可以了

ls –a
rm .DS_Store
4.4.2 自定义分词库
# 运行一个容器 目的是把配置文件模板拷贝出来
jinchengming@MacBook-Pro mydata % docker run -p 80:80 --name nginx -d nginx:1.10
jinchengming@MacBook-Pro mydata % docker container cp nginx:/etc/nginx .
# 重构目录
jinchengming@MacBook-Pro mydata % mv nginx conf
jinchengming@MacBook-Pro mydata % ls
conf		elasticsearch
jinchengming@MacBook-Pro mydata % mkdir nginx
jinchengming@MacBook-Pro mydata % mv conf nginx/
# 先删除原容器 重新运行一个新的容器
docker run -p 80:80 --name nginx -v /Users/jinchengming/mydata/nginx/html:/usr/share/nginx/html -v /Users/jinchengming/mydata/nginx/logs:/var/log/nginx -v /Users/jinchengming/mydata/nginx/conf:/etc/nginx -d nginx:1.10
# 可以在html下新建一个index.html 即可通过127.0.0.1访问到
# 在html同级新建一个es目录,并新建fenci.txt 存放自建分词 可以通过127.0.0.1/es/fenci.txt访问到,乱码可忽略
# 进入es的配置文件,扩展自己的分词库
jinchengming@MacBook-Pro mydata % cd elasticsearch 
jinchengming@MacBook-Pro elasticsearch % ls
config	data	plugins
jinchengming@MacBook-Pro elasticsearch % cd plugins 
jinchengming@MacBook-Pro plugins % ls
analysis-ik
jinchengming@MacBook-Pro plugins % cd analysis-ik 
jinchengming@MacBook-Pro analysis-ik % ls
commons-codec-1.9.jar			config					httpclient-4.5.2.jar			plugin-descriptor.properties
commons-logging-1.2.jar			elasticsearch-analysis-ik-7.4.2.jar	httpcore-4.4.4.jar			plugin-security.policy
jinchengming@MacBook-Pro analysis-ik % cd config 
jinchengming@MacBook-Pro config % ls
IKAnalyzer.cfg.xml		extra_single_word.dic		extra_single_word_low_freq.dic	main.dic			quantifier.dic			suffix.dic
extra_main.dic			extra_single_word_full.dic	extra_stopword.dic		preposition.dic			stopword.dic			surname.dic

# 修改后的配置,指定的ip为容器内nginx的IP
jinchengming@MacBook-Pro config % cat 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://172.17.0.4/es/fenci.txt</entry>
	<!--用户可以在这里配置远程扩展停止词字典-->
	<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

# 配置修改成功后 重启es

5. Springboot整合

Java可以通过两种方式操作es

  1. 9300 TCP
  • spring-data-elasticsearch:transport-api.jar
    • springboot版本不同,transport-api.jar版本不同,不能适配es版本
    • 7.x已经不建议使用,8以后就要废弃
  1. 9200 HTTP
  • JestClient: 非官方,更新慢
  • RestTemplate: 模拟发http请求,ES很多操作要自己封装,麻烦
  • HttpClient: 同上
  • Elasticsearch-Rest-Client: 官方RestClient,封装了ES操作,API层次分明,上手简单

综上,我们选择Elasticsearch-Rest-Client,新建检索微服务,导入依赖

<dependency>
  <groupId>org.elasticsearch.clientgroupId>
  <artifactId>elasticsearch-rest-high-level-clientartifactId>
  <version>7.4.2version>
dependency>

springboot本身也对es做了管理,所以需要自己单独指定项目中对应的es版本号,以下步骤跟踪查询当前版本的springboot管理的es版本

Elasticsearch入门以及整合springboot_第16张图片
Elasticsearch入门以及整合springboot_第17张图片
Elasticsearch入门以及整合springboot_第18张图片

因为不是使用的springdata封装的es,所以我们要自己封装一个配置类

@Configuration
public class SkymailElasticSearchConfig {
    /*
        1. 导入依赖
        2. 编写配置
     */
    public static final RequestOptions COMMON_OPTIONS;
		// options暂时还没加配置
    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();

        COMMON_OPTIONS = builder.build();
    }


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

测试:

@SpringBootTest
class SkymailSearchApplicationTests {
    @Autowired
    private RestHighLevelClient client;
    @Test
    void contextLoads() {
        System.out.println(client);
    }

    /**
     * 测试存储(更新)数据到es
     */
    @Test
    void indexData() throws IOException {
        IndexRequest indexRequest = new IndexRequest("users");
        indexRequest.id("1"); // 数据的id
        User user = new User("chengming", 17, "男");
        String userJson = JSON.toJSONString(user);
        indexRequest.source(userJson, XContentType.JSON); // 要保存的数据
        // 执行操作
        IndexResponse index = client.index(indexRequest, SkymailElasticSearchConfig.COMMON_OPTIONS);
        // 打印响应数据
        System.out.println(index);
    }

    /**
     * 测试复杂查询
     */
    @Test
    void searchData() throws IOException {
        // 1. 创建检索请求
        SearchRequest searchRequest = new SearchRequest();
        // 指定索引
        searchRequest.indices("bank");
        // 指定DSL,即检索条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 构造检索条件
        builder.query(QueryBuilders.matchQuery("address", "mill"));

        // 聚合
        // 1). 安装年龄分布聚合
        TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
        builder.aggregation(ageAgg);
        // 2). 计算平均工资
        AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
        builder.aggregation(balanceAvg);

        System.out.println(builder.toString());
        searchRequest.source(builder);
        // 2. 执行检索
        SearchResponse searchResponse = client.search(searchRequest, SkymailElasticSearchConfig.COMMON_OPTIONS);

        // 3. 分析结果 searchResponse
        System.out.println(searchResponse.toString());
        SearchHits hits = searchResponse.getHits();
        // 获取命中记录 hit
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            Account account = JSON.parseObject(sourceAsString, Account.class);
            System.out.println("account : " + account);
        }
        // 获取聚合数据(分析信息)
        Aggregations aggregations = searchResponse.getAggregations();
        for (Aggregation aggregation : aggregations) {
            System.out.println(aggregation.getName());
        }

        // 或者直接根据聚合名 获取 聚合信息
        Terms ageAgg1 = aggregations.get("ageAgg");
        List<? extends Terms.Bucket> buckets = ageAgg1.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            System.out.println("年龄:" + bucket.getKeyAsString() + " - 人数:" + bucket.getDocCount());
        }

        Avg balanceAvg1 = aggregations.get("balanceAvg");
        System.out.println("平均薪资:" + balanceAvg1.getValueAsString());
    }

}

@Data
@AllArgsConstructor
class User {
    private String username;
    private int age;
    private String gender;
}

@Data
@ToString
class Account {
    private int account_number;
    private int balance;
    private String firstname;
    private String lastname;
    private int age;
    private String gender;
    private String address;
    private String employer;
    private String email;
    private String city;
    private String state;
}

扩展

ElasticSearch7 去掉type概念

  • 关系型数据库中两个数据表示是独立的,即使他们里面有相同的名称的列也不影响使用,但ES中不是这样的。elasticsearch是基于Lucene开发的搜索引擎,而ES中不同type下名称相同的field最终在Lucene中的处理方式是一样的。
    • 两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个field,你必须在两个不同的type中定义相同的field映射,否则,不同type中的相同字段名称就会在处理中出现冲突的情况,导致Lucene处理效率下降
    • 去掉type就是为了提高ES处理数据的效率
  • Elasticsearch 7.x
    • URL中的type参数为可选。比如,索引一个文档不再要求提供文档类型
  • Elasticsearch 8.x
    • 不再支持URL中的type参数
  • 解决:将索引从多类型迁移到单类型,每种类型文档一个独立的索引

你可能感兴趣的:(java,数据库,springcloud,大数据,java,spring,boot,docker)