ElasticSearch
ElasticSearch:
ES是一个基于Lucene实现的开源、分布式、Restful的全文本搜索引擎;此外,它还是一个分布式实时文档存储,其中每个文档的每个field均是被索引的数据,且可被搜索;也是一个带实时分析功能的分布式搜索引擎,能够扩展至数以百计的节点实时处理PB级的数据。
1 | Lucene介绍:http: //www.cnblogs.com/python-gm/p/8400001.html |
基本组件:
- 索引(index):文档容器,换句话说,索引是具有类似属性的文档的集合。类似于表。索引名必须使用小写字母;
- 类型(type):类型是索引内部的逻辑分区,其意义完全取决于用户需求。一个索引内部可定义一个或多个类型。一般来说,类型就是拥有相同的域的文档的预定义。
- 文档(document):文档是Lucene索引和搜索的原子单位,它包含了一个或多个域。是域的容器;基于JSON格式表示。
- 每个域的组成部分:一个名字,一个或多个值;拥有多个值的域,通常称为多值域;
- 映射(mapping):原始内容存储为文档之前需要事先进行分析,例如切词、过滤掉某些词等;映射用于定义此分析机制该如何实现;除此之外,ES还为映射提供了诸如将域中的内容排序等功能。
ES的集群组件:
- Cluster:ES的集群标识为集群名称;默认为"elasticsearch"。节点就是靠此名字来决定加入到哪个集群中。一个节点只能属性于一个集群。
- Node:运行了单个ES实例的主机即为节点。用于存储数据、参与集群索引及搜索操作。节点的标识靠节点名。
- Shard:将索引切割成为的物理存储组件;但每一个shard都是一个独立且完整的索引;
- 创建索引时,ES默认将其分割为5个shard,每个shard也会有一个副本,用户也可以按需自定义,创建完成之后不可修改。
- shard有两种类型:primary shard和replica。Replica用于数据冗余及查询时的负载均衡。每个主shard的副本数量可自定义,且可动态修改。
ES Cluster工作过程:
- 启动时,通过多播(默认)或单播方式在9300/tcp查找同一集群中的其它节点,并与之建立通信。
- 集群中的所有节点会选举出一个主节点负责管理整个集群状态,以及在集群范围内决定各shards的分布方式。站在用户角度而言,每个均可接收并响应用户的各类请求。
- 集群有状态:green, red, yellow
1 | 官方站点:https: //www.elastic.co/ |
ElasticSearch依赖于JDK环境:可以安装配置 Oracle JDK 或 OpenJDK
ES的默认端口:
- 参与集群的事务:9300/tcp
- transport.tcp.port
- 接收请求:9200/tcp
- http.port
Restful API:
- 四类API:
- (1) 检查集群、节点、索引等健康与否,以及获取其相应状态;
- (2) 管理集群、节点、索引及元数据;
- (3) 执行CRUD操作;
- (4) 执行高级操作,例如paging, filtering等;
- ES访问接口:9200/tcp
- curl -X<VERB> '<PROTOCOL>://HOST:PORT/<PATH>?<QUERY_STRING>' -d '<BODY>'
- VERB: GET, PUT, DELETE等;
- PROTOCOL: http, https
- QUERY_STRING:查询参数,例如?pretty表示用易读的JSON格式输出;
- BODY: 请求的主体;
Cluster APIs:
- health:
1 | curl -XGET 'http://172.16.100.67:9200/_cluster/health?pretty' |
- state:
1 | curl -XGET 'http://172.16.100.67:9200/_cluster/state/<metrics>?pretty' |
- stats:
1 | curl -XGET 'http://172.16.100.67:9200/_cluster/stats' |
- 节点状态:
1 | curl -XGET 'http://172.16.100.67:9200/_nodes/stats' |
Plugins:
- 插件扩展ES的功能:
- 添加自定义的映射类型、自定义分析器、本地脚本、自定义发现方式;
- 安装:
- 直接将插件放置于plugins目录中即可;
- 使用plugin脚本进行安装;
1 2 3 4 5 | /usr/share/elasticsearch/bin/plugin -h 参数: -l -i, -- install -r, --remove |
- 站点插件:
1 | http: //HOST :9200 /_plugin/plugin_name |
部署elasticsearch集群:
- 实验环境
1 2 3 | 主机:Ubuntu16.04 elasticsearch版本:6.4.2 |
- 安装java环境
1 2 3 4 5 6 7 8 | sudo apt-get install default-jre # 查看java版本 java -version openjdk version "1.8.0_181" OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-0ubuntu0.16.04.1-b13) OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode) |
- 安装elasticsearch
1 2 3 4 5 6 7 8 9 10 11 | # 首先需要添加 Apt-key: wget -qO - https: //artifacts .elastic.co /GPG-KEY-elasticsearch | sudo apt-key add - # 然后添加 Elasticsearch 的 Repository 定义: echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | sudo tee -a /etc/apt/sources .list.d /elastic-6 .x.list # 安装 Elasticsearch: sudo apt-get update sudo apt-get install elasticsearch # 所有主机完成 Elasticsearch 的安装 |
- 修改主机配置文件
1 2 3 4 5 6 7 | cluster.name: evescn ##集群名称,所有主机配置必须相同 node.name: node-1 ##节点名称,不同主机此处名字不能相同 path.data: /var/lib/elasticsearch path.logs: /var/log/elasticsearch network.host: 0.0.0.0 http.port: 9200 discovery.zen. ping .unicast.hosts: [ "192.168.20.102" , "192.168.20.103" , "192.168.0.104" ] ## 集群地址设置,配置之后集群的主机之间可以自动发现 |
- 查看集群状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # curl -XGET 'http://localhost:9200/_cluster/state?pretty' | less { "cluster_name" : "evescn" , "compressed_size_in_bytes" : 10114, "cluster_uuid" : "lmV_adT3TTGt3kz5_IWeSA" , "version" : 14, "state_uuid" : "c1pcj3nAS5-DyWoCcWXy5w" , "master_node" : "LdRkSjSMSLKH7PtOwDHQIw" , "blocks" : { }, "nodes" : { "LdRkSjSMSLKH7PtOwDHQIw" : { "name" : "node-2" , "ephemeral_id" : "nf0KaKZlQduuz3rWVzxhew" , "transport_address" : "192.168.20.103:9300" , "attributes" : { "ml.machine_memory" : "1021595648" , "ml.max_open_jobs" : "20" , "xpack.installed" : "true" , "ml.enabled" : "true" } }, "LR0zlOMbRF-kxX33VQLtCw" : { "name" : "node-3" , "ephemeral_id" : "gX8srlZWR9GdU2W-B63KIw" , "transport_address" : "192.168.20.104:9300" , "attributes" : { "ml.machine_memory" : "1021595648" , "ml.max_open_jobs" : "20" , "xpack.installed" : "true" , "ml.enabled" : "true" } ...... } |
- 插入数据进行查看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ## 6.X新版本规则,需要指定 -H "Content-Type: application/json" # A主机插入数据 # curl -H "Content-Type: application/json" -XPUT 'localhost:9200/students/class1/2?pretty' -d ' > { > "first_name" : "gm" , > "last_name" : "evescn" , > "gender" : "Man" , > "age" : 23, > "courses" : "ELK" > }' # B主机查看 # curl -XGET 'localhost:9200/students/class1/2?pretty' { "_index" : "students" , "_type" : "class1" , "_id" : "2" , "_version" : 1, "found" : true , "_source" : { "first_name" : "gm" , "last_name" : "evescn" , "gender" : "Man" , "age" : 23, "courses" : "ELK" } |
CRUD操作相关的API:
- 创建文档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | curl -XPUT 'localhost:9200/students/class1/2?pretty' -d ' > { > "first_name" : "Rong" , > "last_name" : "Huang" , > "gender" : "Female" , > "age" : 23, > "courses" : "Luoying Shenjian" > }' { "_index" : "students" , "_type" : "class1" , "_id" : "2" , "_version" : 1, "created" : true } |
- 获取文档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ~] # curl -XGET 'localhost:9200/students/class1/2?pretty' { "_index" : "students" , "_type" : "class1" , "_id" : "2" , "_version" : 1, "found" : true , "_source" : { "first_name" : "Rong" , "last_name" : "Huang" , "gender" : "Female" , "age" : 23, "courses" : "Luoying Shenjian" } |
- 更新文档:
- PUT方法会覆盖原有文档;
- 如果只更新部分内容,得使用_update API
1 2 3 4 5 6 7 8 9 10 | ~] # curl -XPOST 'localhost:9200/students/class1/2/_update?pretty' -d ' { "doc" : { "age" : 22 } }' { "_index" : "students" , "_type" : "class1" , "_id" : "2" , "_version" : 2 } |
- 删除文档:
1 2 3 | DETELE ~] # curl -XDELETE 'localhost:9200/students/class1/2' |
- 删除索引:
1 2 3 | ~] # curl -XDELETE 'localhost:9200/students' ~] # curl -XGET 'localhost:9200/_cat/indices?v' |
查询数据:
- Query API
- Query DSL:JSON based language for building complex queries.
- 用户实现诸多类型的查询操作,比如,simple term query, phrase, range boolean, fuzzy等;
- ES的查询操作执行分为两个阶段:
- 分散阶段
- 合并阶段
- 查询方式:
- 向ES发起查询请求的方式有两种:
- 1、通过Restful request API查询,也称为query string;
- 2、通过发送REST request body进行;
1 2 3 4 5 6 7 8 9 10 | 1、通过Restful request API查询; ~] # curl -XGET 'localhost:9200/students/_search?pretty' 2、通过发送REST request body进行; ~] # curl -XGET 'localhost:9200/students/_search?pretty' -d ' > { > "query" : { "match_all" : {} } > }' |
- 多索引、多类型查询:
1 2 3 4 5 6 7 8 9 10 11 | /_search :所有索引; /INDEX_NAME/_search :单索引; /INDEX1 ,INDEX2 /_search :多索引; /s *,t* /_search :正则匹配搜索 /students/class1/_search :单类型搜索 /students/class1 ,class2 /_search :多类型搜索 |
Mapping和Analysis:
- ES:对每一个文档,会取得其所有域的所有值,生成一个名为“_all”的域;执行查询时,如果在query_string未指定查询的域,则在_all域上执行查询操作;
1 2 3 4 5 6 7 | GET /_search ?q= 'Xianglong' :所有域中出现此字符串的值 GET /_search ?q= 'Xianglong%20Shiba%20Zhang' GET /_search ?q=courses: 'Xianglong%20Shiba%20Zhang' :在courses域中查询此字符串 GET /_search ?q=courses: 'Xianglong' 前两个:表示在_all域搜索; 后两个:在指定的域上搜索; |
- 数据类型:string, numbers, boolean, dates
- 查看指定类型的mapping示例:
1 | ~] # curl 'localhost:9200/students/_mapping/class1?pretty' |
- ES中搜索的数据广义上可被理解为两类:
1 2 3 4 | types:exact full-text 精确值:指未经加工的原始值;在搜索时进行精确匹配; full-text:用于引用文本中数据;判断文档在多大程序上匹配查询请求;即评估文档与用户请求查询的相关度; |
-
- 为了完成full-text搜索,ES必须首先分析文本,并创建出倒排索引;倒排索引中的数据还需进行“正规化”为标准格式;
- 分词
- 正规化 (分词+正规化==》分析)
- 为了完成full-text搜索,ES必须首先分析文本,并创建出倒排索引;倒排索引中的数据还需进行“正规化”为标准格式;
-
- 分析需要由分析器进行:analyzer
- 分析器由三个组件构成:字符过滤器、分词器、分词过滤器
- ES内置的分析器:
- 分析需要由分析器进行:analyzer
1 2 3 4 | Standard analyzer: Simple analyzer Whitespace analyzer Language analyzer |
-
-
- 分析器不仅在创建索引时用到;在构建查询时也会用到;
-
- Query DSL:
1 2 3 4 | request body: 分成两类: query dsl:执行full-text查询时,基于相关度来评判其匹配结果;查询执行过程复杂,且不会被缓存; filter dsl:执行exact查询时,基于其结果为“ yes ”或“no”进行评判;速度快,且结果缓存; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 查询语句的结构: { QUERY_NAME: { AGGUMENT: VALUE, ARGUMENT: VALUE,... } } { QUERY_NAME: { FIELD_NAME: { ARGUMENT: VALUE,... } } } |
- filter dsl:
1 2 3 4 5 6 7 8 9 10 | term filter:精确匹配包含指定term的文档;<br> { "term" : { "name" : "Guo" } } curl -XGET 'localhost:9200/students/_search?pretty' -d { "query" : { "term" : { "name" : "Guo" } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | terms filter:用于多值精确匹配; { "terms" : { "name" : [ "Guo" , "Rong" ] }} range filters:用于在指定的范围内查找数值或时间。 { "range" : "age" : { "gte" : 15, "lte" : 25 } } gt, lt, gte, lte |
1 2 3 4 5 6 | exists and missing filters:存在或不存在<br> { "exists" : { "age" : 25 } } |
1 2 3 4 5 6 7 8 | boolean filter: 基于boolean的逻辑来合并多个filter子句; must:其内部所有的子句条件必须同时匹配,即and; must: { "term" : { "age" : 25 } "term" : { "gender" : "Female" } } |
1 2 3 4 5 | must_not:其所有子句必须不匹配,即not must_not: { "term" : { "age" : 25 } } |
1 2 3 4 5 6 | should:至少有一个子句匹配,即or should: { "term" : { "age" : 25 } "term" : { "gender" : "Female" } } |
- QUERY DSL:
1 2 3 4 | match_all Query: 用于匹配所有文档,没有指定任何query,默认即为match_all query. { "match_all" : {} } |
1 2 3 4 5 6 7 8 | match Query: 在几乎任何域上执行full-text或exact-value查询; 如果执行full-text查询:首先对查询时的语句做分析; { "match" : { "students" : "Guo" }} 如果执行exact-value查询:搜索精确值;此时,建议使用过滤,而非查询; { "match" : { "name" : "Guo" } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | multi_match Query: 用于在多个域上执行相同的查询; { "multi_match" : "query" : full-text search "field" : { 'field1' , 'field2' } } { "multi_match" : "query" : { "students" : "Guo" } "field" : { "name" , "description" } } |
1 2 3 4 5 6 | bool query: 基于boolean逻辑合并多个查询语句;与bool filter不同的是,查询子句不是返回 "yes" 或 "no" ,而是其计算出的匹配度分值。因此,boolean Query会为各子句合并其score; must: must_not: should: |
1 2 3 4 5 6 7 8 | 合并filter和query: { "filterd" : { query: { "match" : { "gender" : "Female" } } filter: { "term" : { "age" : 25}} } } |
- 查询语句语法检查:
1 2 3 4 5 6 7 8 9 10 | GET /INDEX/_validate/query ?pretty { ... } GET /INDEX/_validate/query ?explain&pretty { ... } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程