|
| 1 | +# 简单了解Elasticsearch |
| 2 | +```text |
| 3 | +1.什么是Elasticsearch(简称ES): |
| 4 | + Elasticsearch VS Solr: https://www.cnblogs.com/jajian/p/9801154.html |
| 5 | + [1]基于Apache Lucene构建的开源搜索引擎,提供一个分布式多用户能力的全文搜索引擎; |
| 6 | + [2]用Java编写的,提供简单易用的RESTFul API,当前流行的企业级搜索引擎; |
| 7 | + [3]轻松的横向扩展,可支持PB级的结构化或非结构化数据处理; |
| 8 | + [4]可以准实时地快速存储、搜索、分析海量的数据(用于云计算中,能够达到实时搜索) |
| 9 | +2.应用场景: |
| 10 | + [1]海量数据分析引擎(聚合搜索) |
| 11 | + [2]站内搜索引擎 |
| 12 | + [3]数据仓库 |
| 13 | +3.Elasticsearch有几个核心概念: |
| 14 | + [1]接近实时(NRT): 从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒) |
| 15 | + [2]集群(cluster): |
| 16 | + (1)一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能; |
| 17 | + (2)一个集群由一个唯一的名字标识,这个名字默认就是Elasticsearch; |
| 18 | + 1)这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群; |
| 19 | + 2)在产品环境中显式地设定这个名字是一个好习惯,但是使用默认值来进行测试/开发也是不错的; |
| 20 | + [3]节点(node): |
| 21 | + (1)每个节点是集群中的一个服务器,作为集群的一部分,它存储数据并参与集群的索引和搜索功能; |
| 22 | + (2)和集群类似,每个节点由一个名字来标识的; |
| 23 | + 1)默认情况下,这个名字是一个随机的漫威漫画角色的名字,该名字会在启动的时候赋予节点; |
| 24 | + 2)节点名字对于管理工作来说挺重要的,因为在这个管理过程中,会去确定网络中的哪些服务器对应于Elasticsearch集群中的哪些节点; |
| 25 | + (3)一个节点可以通过配置集群名称的方式来加入一个指定的集群; |
| 26 | + 默认情况下,每个节点都会被安排加入到一个叫做Elasticsearch的集群中; |
| 27 | + (4)在一个集群里,可以拥有任意多个节点; |
| 28 | + 如果当前网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做Elasticsearch的集群; |
| 29 | + [4]索引(index): |
| 30 | + (1)一个索引就是一个拥有几分相似特征的文档的集合; |
| 31 | + (2)一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引,搜索,更新和删除的时,都要使用到这个名字; |
| 32 | + (3)索引类似于关系型数据库中Database的概念; |
| 33 | + [5]类型(type): |
| 34 | + (1)在一个索引中,可以定义一种或多种类型;一个类型是你的索引的一个逻辑上的分类/分区;通常,会为具有一组共同字段的文档定义一个类型; |
| 35 | + (2)类型类似于关系型数据库中Table的概念; |
| 36 | + [6]文档(document): |
| 37 | + (1)一个文档是一个可被索引的基础信息单元; |
| 38 | + 文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式; |
| 39 | + (2)一个文档,物理上存在于一个索引之中,但文档必须被索引赋予一个类型type; |
| 40 | + (3)文档类似于关系型数据库中Record的概念;实际上一个文档除了用户定义的数据外,还包括**_index**、_type和**_id**字段; |
| 41 | + [7]分片和复制(shards & replicas): |
| 42 | + (1)一个索引可以存储超出单个结点硬件限制的大量数据; |
| 43 | + (2)为了解决索引存储超单节点硬件限制问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片; |
| 44 | + 1)当你创建一个索引的时候,可指定想要的分片的数量; |
| 45 | + 2)每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上; |
| 46 | + 3)分片之所以重要,主要有两方面的原因: |
| 47 | + 允许你水平分割/扩展你的内容容量; |
| 48 | + 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量; |
| 49 | + (3)某个分片/节点随时可能处于离线状态,因此需要一个故障转移机制;为此Elasticsearch允许创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制; |
| 50 | + 1)复制之所以重要,主要有两方面的原因: |
| 51 | + 在分片/节点失败的情况下,提供了高可用性;因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的; |
| 52 | + 扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行; |
| 53 | + (4)每个索引可以被分成多个分片;一个索引也可以被复制0次(意思是没有复制)或多次; |
| 54 | + 1)一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别; |
| 55 | + 2)分片和复制的数量可以在索引创建的时候指定;在索引创建之后,可在任何时候动态地改变复制数量,但是不能改变分片的数量; |
| 56 | + (5)默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制; |
| 57 | + 1)即集群中至少有两个节点,索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片; |
| 58 | + 2)一个索引的多个分片可存放在集群中的一台主机上,也可以存放在多台主机上,这取决于你的集群机器数量; |
| 59 | + 主分片和复制分片的具体位置是由ES内在的策略所决定的; |
| 60 | + [8]数据结构及对比 |
| 61 | + (1)Elasticsearch的结构: |
| 62 | + 1)索引: 含有相同属性的文档集合; |
| 63 | + 2)类型: 索引可以定义一个或多个类型,文档必须属于一个类型; |
| 64 | + 3)文档: 可以被索引的基础数据单位; |
| 65 | + 4)分片: 每个索引都有多个分片,每个分片都是Lucene索引; |
| 66 | + 5)备份: 拷贝一份分片就完成分片的备份; |
| 67 | + (2)Mysql和Elasticsearch对应关系: |
| 68 | + Mysql Elasticsearch |
| 69 | + Database Index |
| 70 | + Table Type |
| 71 | + Row Document |
| 72 | + Column Field |
| 73 | + Schema Mapping |
| 74 | + Index Everything is indexed |
| 75 | + SQL Query DSL |
| 76 | +``` |
| 77 | +# 安装本地Elasticsearch |
| 78 | +```text |
| 79 | +1.本地Elasticsearch单机搭建: |
| 80 | + [1]首先要安装JDK1.8的环境及以上版本都行,不能低于1.8;安装Windows本地版,去Elasticsearch官网下载zip压缩包并解压即可; |
| 81 | + (1)目录说明: |
| 82 | + 1)config: 配置文件 |
| 83 | + 2)modules: 模块存放目录 |
| 84 | + 3)bin: 脚本 |
| 85 | + 4)lib: 第三方库 |
| 86 | + 5)plugins: 第三方插件 |
| 87 | + (2)直接运行bin下的elasticsearch.bat这个文件即可启动,然后访问本机的127.0.0.1:9200即可;关闭窗口就是关闭服务; |
| 88 | +2.安装本地Elasticsearch集群(分布式): |
| 89 | + [1]安装说明: 三个节点,一个Master,两个Slave,名称要相同,9500端口为Master节点,其余两个为Slave节点: |
| 90 | + 集群名称 IP-端口 |
| 91 | + myEsCluster 127.0.0.1:9500 |
| 92 | + myEsCluster 127.0.0.1:9600 |
| 93 | + myEsCluster 127.0.0.1:9700 |
| 94 | + [2]ES安装包解压出三份ES,修改每个Elasticsearch安装目录下的config/elasticsearch.yml配置文件: |
| 95 | + (1)Master配置说明: |
| 96 | + # 设置支持Elasticsearch-Head |
| 97 | + http.cors.enabled: true |
| 98 | + http.cors.allow-origin: "*" |
| 99 | + # 设置集群Master配置信息 |
| 100 | + cluster.name: myEsCluster |
| 101 | + # 节点的名字,一般为Master或者Slave |
| 102 | + node.name: master |
| 103 | + # 节点是否为Master,设置为true的话,说明此节点为Master节点 |
| 104 | + node.master: true |
| 105 | + # 设置网络,如果是本机的话就是127.0.0.1,其他服务器配置对应的IP地址即可(0.0.0.0支持外网访问) |
| 106 | + network.host: 127.0.0.1 |
| 107 | + # 设置对外服务的Http端口,默认为 9200,可以修改默认设置 |
| 108 | + http.port: 9500 |
| 109 | + # 设置节点间交互的TCP端口,默认是9300 |
| 110 | + transport.tcp.port: 9300 |
| 111 | + # 手动指定可以成为Master的所有节点的Name或者IP,这些配置将会在第一次选举中进行计算 |
| 112 | + cluster.initial_master_nodes: ["127.0.0.1"] |
| 113 | + (2)Slave配置说明: |
| 114 | + 1)Slave1: |
| 115 | + # 设置集群Slave配置信息 |
| 116 | + cluster.name: myEsCluster |
| 117 | + # 节点的名字,一般为Master或者Slave |
| 118 | + node.name: slave1 |
| 119 | + # 节点是否为Master,设置为true的话,说明此节点为master节点 |
| 120 | + node.master: false |
| 121 | + # 设置对外服务的Http端口,默认为 9200,可以修改默认设置 |
| 122 | + http.port: 9600 |
| 123 | + # 设置网络,如果是本机的话就是127.0.0.1,其他服务器配置对应的IP地址即可(0.0.0.0支持外网访问) |
| 124 | + network.host: 127.0.0.1 |
| 125 | + # 集群发现 |
| 126 | + discovery.seed_hosts: ["127.0.0.1:9300"] |
| 127 | + 2)Slave2: |
| 128 | + # 设置集群Slave配置信息 |
| 129 | + cluster.name: myEsCluster |
| 130 | + # 节点的名字,一般为Master或者Slave |
| 131 | + node.name: slave2 |
| 132 | + # 节点是否为Master,设置为true的话,说明此节点为master节点 |
| 133 | + node.master: false |
| 134 | + # 设置对外服务的Http端口,默认为 9200,可以修改默认设置 |
| 135 | + http.port: 9700 |
| 136 | + # 设置网络,如果是本机的话就是127.0.0.1,其他服务器配置对应的IP地址即可(0.0.0.0支持外网访问) |
| 137 | + network.host: 127.0.0.1 |
| 138 | + # 集群发现 |
| 139 | + discovery.seed_hosts: ["127.0.0.1:9300"] |
| 140 | + [3]配置后完成后,启动一个Master,两个Slave;访问http://localhost:9500/_cat/nodes?v; |
| 141 | +``` |
| 142 | +# 安装本地分词插件(IK和拼音) |
| 143 | +```text |
| 144 | +1.安装本地Elasticsearch的IK分词插件: |
| 145 | + [1]IK分词器(需要版本对应)下载地址: https://github.com/medcl/elasticsearch-analysis-ik/releases |
| 146 | + [2]解压分词插件的压缩包到Elasticsearch目录的plugins目录下: |
| 147 | + 例如: elasticsearch-7.6.0\plugins\elasticsearch-analysis-ik-7.6.0 |
| 148 | + [3]重启Elasticsearch,在控制台上看到分词插件加载的日志,则分词安装成功; |
| 149 | + loaded plugin [analysis-ik] |
| 150 | + [4]测试: |
| 151 | + POST /_analyze |
| 152 | + { |
| 153 | + "text":"中华人民共和国国徽", |
| 154 | + "analyzer":"ik_smart" |
| 155 | + } |
| 156 | + POST /_analyze |
| 157 | + { |
| 158 | + "text":"中华人民共和国国徽", |
| 159 | + "analyzer":"ik_max_word" |
| 160 | + } |
| 161 | +2.安装本地Elasticsearch的拼音分词插件: |
| 162 | + [1]拼音分词器(需要版本对应)下载地址:https://github.com/medcl/elasticsearch-analysis-pinyin/releases |
| 163 | + [2]解压分词插件的压缩包到Elasticsearch目录的plugins目录下: |
| 164 | + elasticsearch-7.6.0\plugins\elasticsearch-analysis-pinyin-7.6.0 |
| 165 | + [3]重启Elasticsearch,在控制台上看到分词插件加载的日志,则分词安装成功; |
| 166 | + loaded plugin [analysis-pinyin] |
| 167 | + [4]测试: |
| 168 | + POST /_analyze |
| 169 | + { |
| 170 | + "text":"中华人民共和国国徽", |
| 171 | + "analyzer":"pinyin" |
| 172 | + } |
| 173 | +``` |
| 174 | +# SpringBoot整合Elasticsearch |
| 175 | +```text |
| 176 | +1.SpringBoot整合Elasticsearch的方式(TransportClient、Data-ES、Elasticsearch SQL、REST Client): |
| 177 | + [1]TransportClient: |
| 178 | + TransportClient即将弃用,所以这种方式不考虑; |
| 179 | + [2]Data-ES: |
| 180 | + (1)Spring提供的封装的方式,好像底层也是基于TransportClient,Elasticsearch7.0后的版本不怎么支持; |
| 181 | + (2)Spring Data Elasticsearch版本与Elasticsearch官网版本差太多; |
| 182 | + [3]Elasticsearch SQL: |
| 183 | + 将Elasticsearch的Query DSL用SQL转换查询,早期有一个第三方的插件Elasticsearch-SQL,后来随着官方也开始做这方面,该插件不怎么更新了; |
| 184 | + 参考: https://www.cnblogs.com/jajian/p/10053504.html |
| 185 | + [4]REST Client: |
| 186 | + (1)官方推荐使用,分为两个Low Level REST Client和High Level REST Client; |
| 187 | + (2)Low Level REST Client是早期出的API比较简陋了,还需要自己去拼写Query DSL; |
| 188 | + (3)High Level REST Client使用起来更好用,更符合面向对象的感觉; |
| 189 | +2.创建index和mapping: |
| 190 | + [1]创建Index,拼音分词过滤: |
| 191 | + PUT /book |
| 192 | + { |
| 193 | + "settings": { |
| 194 | + "analysis": { |
| 195 | + "analyzer": { |
| 196 | + "pinyin_analyzer": { |
| 197 | + "tokenizer": "my_pinyin" |
| 198 | + } |
| 199 | + }, |
| 200 | + "tokenizer": { |
| 201 | + "my_pinyin": { |
| 202 | + "type": "pinyin", |
| 203 | + "keep_separate_first_letter": false, |
| 204 | + "keep_full_pinyin": true, |
| 205 | + "keep_original": true, |
| 206 | + "limit_first_letter_length": 16, |
| 207 | + "lowercase": true, |
| 208 | + "remove_duplicated_term": true |
| 209 | + } |
| 210 | + } |
| 211 | + } |
| 212 | + } |
| 213 | + } |
| 214 | + 返回: |
| 215 | + { |
| 216 | + "acknowledged": true, |
| 217 | + "shards_acknowledged": true, |
| 218 | + "index": "book" |
| 219 | + } |
| 220 | + [2]创建Mapping,属性使用过滤,name开启拼音分词,content开启IK分词,describe开启拼音加IK分词: |
| 221 | + POST /book/_mapping |
| 222 | + { |
| 223 | + "properties": { |
| 224 | + "name": { |
| 225 | + "type": "keyword", |
| 226 | + "fields": { |
| 227 | + "pinyin": { |
| 228 | + "type": "text", |
| 229 | + "store": false, |
| 230 | + "term_vector": "with_offsets", |
| 231 | + "analyzer": "pinyin_analyzer", |
| 232 | + "boost": 10 |
| 233 | + } |
| 234 | + } |
| 235 | + }, |
| 236 | + "content": { |
| 237 | + "type": "text", |
| 238 | + "analyzer": "ik_max_word", |
| 239 | + "search_analyzer": "ik_smart" |
| 240 | + }, |
| 241 | + "describe": { |
| 242 | + "type": "text", |
| 243 | + "analyzer": "ik_max_word", |
| 244 | + "search_analyzer": "ik_smart", |
| 245 | + "fields": { |
| 246 | + "pinyin": { |
| 247 | + "type": "text", |
| 248 | + "store": false, |
| 249 | + "term_vector": "with_offsets", |
| 250 | + "analyzer": "pinyin_analyzer", |
| 251 | + "boost": 10 |
| 252 | + } |
| 253 | + } |
| 254 | + }, |
| 255 | + "id": { |
| 256 | + "type": "long" |
| 257 | + } |
| 258 | + } |
| 259 | + } |
| 260 | + 返回: |
| 261 | + { |
| 262 | + "acknowledged": true |
| 263 | + } |
| 264 | +2.创建一个SpringBoot 2.2.6的Maven项目,添加如下REST Client依赖和其他用到的依赖: |
| 265 | + <dependency> |
| 266 | + <groupId>org.springframework.boot</groupId> |
| 267 | + <artifactId>spring-boot-starter-web</artifactId> |
| 268 | + </dependency> |
| 269 | + <dependency> |
| 270 | + <groupId>org.springframework.boot</groupId> |
| 271 | + <artifactId>spring-boot-starter-thymeleaf</artifactId> |
| 272 | + </dependency> |
| 273 | + <!-- Java Low Level REST Client --> |
| 274 | + <dependency> |
| 275 | + <groupId>org.elasticsearch.client</groupId> |
| 276 | + <artifactId>elasticsearch-rest-client</artifactId> |
| 277 | + <version>7.6.0</version> |
| 278 | + </dependency> |
| 279 | + <!-- Java High Level REST Client --> |
| 280 | + <dependency> |
| 281 | + <groupId>org.elasticsearch.client</groupId> |
| 282 | + <artifactId>elasticsearch-rest-high-level-client</artifactId> |
| 283 | + <version>7.6.0</version> |
| 284 | + </dependency> |
| 285 | + <dependency> |
| 286 | + <groupId>com.alibaba</groupId> |
| 287 | + <artifactId>fastjson</artifactId> |
| 288 | + <version>1.2.68</version> |
| 289 | + </dependency> |
| 290 | + <!-- Commons-Lang3工具包 --> |
| 291 | + <dependency> |
| 292 | + <groupId>org.apache.commons</groupId> |
| 293 | + <artifactId>commons-lang3</artifactId> |
| 294 | + <version>3.10</version> |
| 295 | + </dependency> |
| 296 | +3.配置文件: |
| 297 | + server: |
| 298 | + port: 8080 |
| 299 | + spring: |
| 300 | + application: |
| 301 | + name: springboot-elasticsearch |
| 302 | + thymeleaf: |
| 303 | + # 开发时关闭缓存不然没法看到实时页面 |
| 304 | + cache: off |
| 305 | + # 启用不严格检查 |
| 306 | + mode: LEGACYHTML5 |
| 307 | + # Elasticsearch配置 |
| 308 | + elasticsearch: |
| 309 | + hostname: localhost |
| 310 | + port: 9200 |
| 311 | +4.编写配置类: |
| 312 | + @Configuration |
| 313 | + public class RestClientConfig { |
| 314 | + @Value("${elasticsearch.hostname}") |
| 315 | + private String hostname; |
| 316 | + @Value("${elasticsearch.port}") |
| 317 | + private int port; |
| 318 | + /** |
| 319 | + * LowLevelRestConfig |
| 320 | + * |
| 321 | + * @return org.elasticsearch.client.RestClient |
| 322 | + */ |
| 323 | + @Bean |
| 324 | + public RestClient restClient() { |
| 325 | + // 如果有多个从节点可以持续在内部new多个HttpHost,参数1是IP,参数2是端口,参数3是通信协议 |
| 326 | + RestClientBuilder clientBuilder = RestClient.builder(new HttpHost(hostname, port, "http")); |
| 327 | + // 设置Header编码 |
| 328 | + Header[] defaultHeaders = {new BasicHeader("content-type", "application/json")}; |
| 329 | + clientBuilder.setDefaultHeaders(defaultHeaders); |
| 330 | + // 添加其他配置,这些配置都是可选的 |
| 331 | + // 详情配置可看https://blog.csdn.net/jacksonary/article/details/82729556 |
| 332 | + return clientBuilder.build(); |
| 333 | + } |
| 334 | + /** |
| 335 | + * HighLevelRestConfig |
| 336 | + * |
| 337 | + * @return org.elasticsearch.client.RestClient |
| 338 | + */ |
| 339 | + @Bean |
| 340 | + public RestHighLevelClient restHighLevelClient() { |
| 341 | + // 如果有多个从节点可以持续在内部new多个HttpHost,参数1是IP,参数2是端口,参数3是通信协议 |
| 342 | + return new RestHighLevelClient(RestClient.builder(new HttpHost(hostname, port, "http"))); |
| 343 | + } |
| 344 | + } |
| 345 | +4.其余代码见demo; |
| 346 | +``` |
0 commit comments