ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。ElasticSearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
官方网址:https://www.elastic.co/cn/products/elasticsearch
Github:https://github.com/elastic/elasticsearch
1、elasticsearch是一个基于Lucene的高扩展的分布式搜索服务器,支持开箱即用。
2、elasticsearch隐藏了Lucene的复杂性,对外提供Restful 接口来操作索引、搜索。
3、扩展性好,可部署上百台服务器集群,处理PB级数据。
4、近实时的去索引数据、搜索数据。
索引结构分为逻辑结构和物理结构。
逻辑结构部分是一个倒排索引表:
1、将要搜索的文档内容分词,所有不重复的词组成分词列表。
2、将搜索的文档最终以Document方式存储起来。
3、每个词和docment都有关联。
例子:
Term Doc_1 Doc_2
----------------------
Quick | | x |
The | x | x |
brown | x | x |
Dog | x | |
Fox | x | x |
Lazy | | x |
quick | x | |
如果我们想搜索 quick brown
,我们只需要查找包含每个词条的文档:
Term Doc_1 Doc_2
----------------------
quick | x | |
brown | x | x |
两个文档都匹配,但是第一个文档比第二个匹配度更高。如果我们使用仅计算匹配词条数量的简单相似性算法 ,那么,我们可以说,对于我们查询的相关性来讲,第一个文档比第二个文档更佳。
Elasticsearch提供 RESTful Api接口进行索引、搜索,并且支持多种客户端。
如何在项目中使用?
1)用户在前端搜索关键字
2)项目前端通过http方式请求项目服务端 ,项目服务端可定制搜索
3)项目服务端通过Http RESTful方式请求ES集群进行搜索
4)ES集群从索引库检索数据。
1、新版本要求至少jdk1.8以上。
2、支持tar、zip、rpm等多种安装方式,在windows下开发建议使用ZIP安装方式。
3、支持docker方式安装 详细参见:https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html
解压 elasticsearch-6.2.1.zip
bin:脚本目录,包括:启动、停止等可执行脚本
config:配置文件目录
data:索引目录,存放索引文件的地方
logs:日志目录
modules:模块目录,包括了es的功能模块
plugins:插件目录,es支持插件机制
ES的配置文件的地址根据安装形式的不同而不同:
使用zip、tar安装,配置文件的地址在安装目录的confifig下。
使用RPM安装,配置文件在/etc/elasticsearch下。
使用MSI安装,配置文件的地址在安装目录的confifig下,并且会自动将confifig目录地址写入环境变量 ES_PATH_CONF。
配置文件如下:
elasticsearch.yml:用于配置Elasticsearch运行参数
jvm.options::用于配置ElasticSearch JVM设置
log4j2.properties:用于配置ElasticSearch日志
配置格式是YAML,可以采用如下两种方式:
方式1:层次方式
path:
data: /var/lib/elasticsearch
logs: /var/log/elasticsearch
方式2:属性方式
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
配置例子:
cluster.name: xuecheng
node.name: xc_node_1
network.host: 0.0.0.0
http.port: 9200
transport.tcp.port: 9300
node.master: true
node.data: true
#discovery.zen.ping.unicast.hosts: ["0.0.0.0:9300", "0.0.0.0:9301", "0.0.0.0:9302"]
discovery.zen.minimum_master_nodes: 1
bootstrap.memory_lock: false
node.max_local_storage_nodes: 1
#注意path.data和path.logs路径配置正确。
path.data: D:\ElasticSearch\elasticsearch‐6.2.1\data
path.logs: D:\ElasticSearch\elasticsearch‐6.2.1\logs
http.cors.enabled: true
http.cors.allow‐origin: /.*/
常用的配置项如下:
cluster.name:配置elasticsearch的集群名称,默认是elasticsearch。建议修改成一个有意义的名称。
node.name:节点名,通常一台物理服务器就是一个节点,es会默认随机指定一个名字,建议指定一个有意义的名称,方便管理。一个或多个节点组成一个cluster集群,集群是一个逻辑的概念,节点是物理概念。
path.conf:设置配置文件的存储路径,tar或zip包安装默认在es根目录下的confifig文件夹,rpm安装默认在/etc/elasticsearch
path.data:设置索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开。 path.logs:设置日志文件的存储路径,默认是es根目录下的logs文件夹
path.plugins:设置插件的存放路径,默认是es根目录下的plugins文件夹
bootstrap.memory_lock: true 设置为true可以锁住ES使用的内存,避免内存与swap分区交换数据。
network.host:设置绑定主机的ip地址,设置为0.0.0.0表示绑定任何ip,允许外网访问,生产环境建议设置为具体 的ip。
http.port:设置对外服务的http端口,默认为9200。
transport.tcp.port:集群结点之间通信端口
node.master:指定该节点是否有资格被选举成为master结点,默认是true,如果原来的master宕机会重新选举新 的master。
node.data:指定该节点是否存储索引数据,默认为true。
discovery.zen.ping.unicast.hosts: ["host1:port", "host2:port", "..."] :设置集群中master节点的初始列表。
discovery.zen.ping.timeout: 3s :设置ES自动发现节点连接超时的时间,默认为3秒,如果网络延迟高可设置大些。
discovery.zen.minimum_master_nodes:主结点数量的最少值 ,此值的公式为:(master_eligible_nodes / 2) + 1 ,比如:有3个符合要求的主结点,那么这里要设置为2。
node.max_local_storage_nodes:单机允许的最大存储结点数,通常单机启动一个结点建议设置为1,开发环境如果单机启动多个节点可设置大于1.
设置最小及最大的JVM堆内存大小:
在jvm.options中设置 -Xms和-Xmx:
1) 两个值设置为相等
2) 将 Xmx 设置为不超过物理内存的一半
日志文件设置,ES使用log4j,注意日志级别的配置。
在linux上根据系统资源情况,可将每个进程最多允许打开的文件数设置大些。
su limit -n 查询当前文件数
使用命令设置limit:
先切换到root,设置完成再切回elasticsearch用户。
sudo su
ulimit ‐n 65536
su elasticsearch
也可通过下边的方式修改文件进行持久设置
/etc/security/limits.conf 将下边的行加入此文件:
elasticsearch ‐ nofile 65536
在windows环境下,进入安装的bin目录下,直接运行脚本elasticsearch.bat,浏览器输入:http://localhost:9200 ,如果出现以下内容,则证明启动成功:
{
"name" : "xc_node_1",
"cluster_name" : "xuecheng",
"cluster_uuid" : "z9Vb5SIjRySnO6TmKLT1zw",
"version" : {
"number" : "6.2.1",
"build_hash" : "7299dc3",
"build_date" : "2018-02-07T19:34:26.990113Z",
"build_snapshot" : false,
"lucene_version" : "7.2.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
head插件是ES的一个可视化管理插件,用来监视ES的状态,并通过head客户端和ES服务进行交互,比如创建映 射、创建索引等,head的项目地址在https://github.com/mobz/elasticsearch-head 。
从ES6.0开始,head插件支持使得node.js运行。
1、安装node.js
2、下载head并运行
git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install
npm run start
打开浏览器调试工具发现报错:Origin null is not allowed by Access-Control-Allow-Origin.
原因是:head插件作为客户端要连接ES服务(localhost:9200),此时存在跨域问题,elasticsearch默认不允许跨域访问。
解决方案:设置elasticsearch允许跨域访问。
在config/elasticsearch.yml 后面增加以下参数:
#开启cors跨域访问支持,默认为false
http.cors.enabled: true
#跨域访问允许的域名地址,(允许所有域名)以上使用正则
http.cors.allow-origin: /.*/
注意:将config/elasticsearch.yml另存为utf-8编码格式。
ES的索引库是一个逻辑概念,它包括了分词列表及文档列表,同一个索引库中存储了相同类型的文档。它就相当于MySQL中的表,或相当于Mongodb中的集合。
关于索引这个语:
索引(名词):ES是基于Lucene构建的一个搜索服务,它要从索引库搜索符合条件索引数据。
索引(动词):索引库刚创建起来是空的,将数据添加到索引库的过程称为索引。
下边介绍两种创建索引库的方法,它们的工作原理是相同的,都是客户端向ES服务发送命令。
1)使用postman或curl这样的工具创建: 使用put发送请求:http://localhost:9200/索引库名称
//发送json数据
{
"settings": {
"index": {
// 分片数量
"number_of_shards": 1,
// 副本数量
"number_of_replicas":0
}
}
}
响应数据:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "xc_course"
}
number_of_shards:设置分片的数量,在集群中通常设置多个分片,表示一个索引库将拆分成多片分别存储不同 的结点,提高了ES的处理能力和高可用性,入门程序使用单机环境,这里设置为1。
number_of_replicas:设置副本的数量,设置副本是为了提高ES的高可靠性,单机环境设置为0。
1)概念说明:
在索引中每个文档都包括了一个或多个field,创建映射就是向索引库中创建field的过程,下边是document和field与关系数据库的概念的类比:文档(Document)--------Row记录;字段(Field)----------Columns 列
注意:6.0之前的版本有type(类型)概念,type相当于关系数据库的表,ES官方将在ES9.0版本中彻底删除type。
上边讲的创建索引库相当于关系数据库中的数据库还是表?
1、如果相当于数据库就表示一个索引库可以创建很多不同类型的文档,这在ES中也是允许的。
2、如果相当于表就表示一个索引库只能存储相同类型的文档,ES官方建议在一个索引库中只存储相同类型的文
档。
2)创建映射
发送post请求:http://localhost:9200/索引库名称/类型名称/_mapping
由于ES6.0版本还没有将type彻底删除,所以暂时把type起一个没有特殊意义的名字。
// 使用Postman发送Post请求:http://localhost:9200/xc_course/doc/_mapping
// 发送的数据为:
{
"properties": {
"name": {
"type": "text"
},
"description": {
"type": "text"
},
"studymodel": {
"type": "keyword"
}
}
}
注意:在xc_course索引库下的doc类型下创建映射。doc是类型名,可以自定义,在ES6.0中要弱化类型的概念,
给它起一个没有具体业务意义的名称。
// 接收到的数据为:
{
"acknowledged": true
}
可使用Postman发送Get请求到同一地址,查询映射信息:
// 使用Postman发送Get请求:http://localhost:9200/xc_course/doc/_mapping
// 响应的数据格式为:
{
"xc_course": {
"mappings": {
"doc": {
"properties": {
"description": {
"type": "text"
},
"name": {
"type": "text"
},
"studymodel": {
"type": "keyword"
}
}
}
}
}
}
ES中的文档相当于MySQL数据库表中的记录。发送Put或Post请求:http://localhost:9200/xc_course/doc/id值 (如果不指定id值ES会自动生成ID)
// 使用Postman发送Put或Post请求:http://localhost:9200/xc_course/doc/4028e58161bcf7f40161bcf8b77c0000
// 请求的数据为:
{
"name":"Bootstrap开发框架",
"description":"Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"studymodel":"201001"
}
// 响应的数据为:
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0000",
"_version": 1,
"result": "created",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
1、根据课程id查询文档
// 发送Get请求:http://localhost:9200/xc_course/doc/4028e58161bcf7f40161bcf8b77c0000
// 响应的数据格式为:
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0000",
"_version": 1,
"found": true,
"_source": {
"name": "Bootstrap开发框架",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"studymodel": "201001"
}
}
2、查询所有记录
// 发送Get请求:http://localhost:9200/xc_course/doc/_search
// 响应的数据格式为:
{
"took": 110,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.0,
"hits": [
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0000",
"_score": 1.0,
"_source": {
"name": "Bootstrap开发框架",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"studymodel": "201001"
}
}
]
}
}
took:本次操作花费的时间,单位为毫秒。
timed_out:请求是否超时
_shards:说明本次操作共搜索了哪些分片
hits:搜索命中的记录
hits.total : 符合条件的文档总数 hits.hits :匹配度较高的前N个文档
hits.max_score:文档匹配得分,这里为最高分
_score:每个文档都有一个匹配度得分,按照降序排列。
_source:显示了文档的原始内容。
3、查询名称中包括bootstrap关键字的的记录
发送Get请求:http://localhost:9200/xc_course/doc/_search?q=name:bootstrap
4、查询学习模式为201001的记录
发送Get请求:http://localhost:9200/xc_course/doc/_search?q=studymodel:201001
5、删除文档:根据课程id使用Delete请求删除文档
http://localhost:9200/xc_course/doc/4028e58161bcf7f40161bcf8b77c0001
// 响应的数据为:
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0001",
"_version": 2,
"result": "deleted",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}
ES更新文档的顺序是:先检索到文档、将原来的文档标记为删除、创建新文档、删除旧文档,创建新文档就会重建索引。
通过请求Url有两种方法:
1、完全替换:Post请求:http://localhost:9200/xc_test/doc/3
// 请求的数据为:
{
"name": "spring cloud实战",
"description": "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud 基础入门。",
"studymodel": "201001",
"price": 5.6
}
// 响应的数据为:
{
"_index": "xc_test",
"_type": "doc",
"_id": "3",
"_version": 2,
"result": "updated",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
2、局部更新:下边的例子是只更新price字段,Post请求:http://localhost:9200/xc_test/doc/3/_update
// 请求的数据为:
{ "doc":{"price":66.6} }
// 响应的数据为:
{
"_index": "xc_test",
"_type": "doc",
"_id": "3",
"_version": 3,
"result": "updated",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}
// Get请求:http://localhost:9200/xc_test/doc/3,可查询到price字段的值已更新
1、根据id删除,格式如下:Delete请求:http://localhost:9200/{index}/{type}/{id}
2、搜索匹配删除,将搜索出来的记录删除,格式如下:Post请求:http://localhost:9200/{index}/{type}/_delete_by_query
// 搜索条件的数据为:
{
"query": {
"term": {
"studymodel": "201001"
}
}
}
// 响应的数据为:
{
"took": 57,
"timed_out": false,
"total": 1,
"deleted": 1,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1.0,
"throttled_until_millis": 0,
"failures": []
}
在添加文档时会进行分词,索引中存放的就是一个一个的词(term),当你去搜索时就是拿关键字去匹配词,最终找到词关联的文档。
测试当前索引库使用的分词器:
// 发送Post请求:http://localhost:9200/_analyze
// 发送的数据为:
{
"text":"测试分词器,后边是测试内容:spring cloud实战"
}
// 响应的数据为:
{
"tokens": [
{
"token": "测",
"start_offset": 0,
"end_offset": 1,
"type": "<IDEOGRAPHIC>",
"position": 0
},
{
"token": "试",
"start_offset": 1,
"end_offset": 2,
"type": "<IDEOGRAPHIC>",
"position": 1
},
{
"token": "分",
"start_offset": 2,
"end_offset": 3,
"type": "<IDEOGRAPHIC>",
"position": 2
},
{
"token": "词",
"start_offset": 3,
"end_offset": 4,
"type": "<IDEOGRAPHIC>",
"position": 3
},
{
"token": "器",
"start_offset": 4,
"end_offset": 5,
"type": "<IDEOGRAPHIC>",
"position": 4
},
{
"token": "后",
"start_offset": 6,
"end_offset": 7,
"type": "<IDEOGRAPHIC>",
"position": 5
},
{
"token": "边",
"start_offset": 7,
"end_offset": 8,
"type": "<IDEOGRAPHIC>",
"position": 6
},
{
"token": "是",
"start_offset": 8,
"end_offset": 9,
"type": "<IDEOGRAPHIC>",
"position": 7
},
{
"token": "测",
"start_offset": 9,
"end_offset": 10,
"type": "<IDEOGRAPHIC>",
"position": 8
},
{
"token": "试",
"start_offset": 10,
"end_offset": 11,
"type": "<IDEOGRAPHIC>",
"position": 9
},
{
"token": "内",
"start_offset": 11,
"end_offset": 12,
"type": "<IDEOGRAPHIC>",
"position": 10
},
{
"token": "容",
"start_offset": 12,
"end_offset": 13,
"type": "<IDEOGRAPHIC>",
"position": 11
},
{
"token": "spring",
"start_offset": 14,
"end_offset": 20,
"type": "<ALPHANUM>",
"position": 12
},
{
"token": "cloud",
"start_offset": 21,
"end_offset": 26,
"type": "<ALPHANUM>",
"position": 13
},
{
"token": "实",
"start_offset": 26,
"end_offset": 27,
"type": "<IDEOGRAPHIC>",
"position": 14
},
{
"token": "战",
"start_offset": 27,
"end_offset": 28,
"type": "<IDEOGRAPHIC>",
"position": 15
}
]
}
会发现分词的效果将 "测试" 这个词拆分成两个单字"测"和"试",这是因为当前索引库使用的分词器对中文就是单字
分词。
使用IK分词器可以实现对中文分词的效果。
下载IK分词器:(Github地址:https://github.com/medcl/elasticsearch-analysis-ik) 找到对应的版本
解压,并将解压的文件拷贝到ES安装目录的plugins下的ik目录下,并重启ES
// 发送Post请求:http://localhost:9200/_analyze
// 发送的数据为:
{
"text":"测试分词器,后边是测试内容:spring cloud实战",
"analyzer":"ik_max_word"
}
// 响应的数据为:
{
"tokens": [
{
"token": "测试",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "分词器",
"start_offset": 2,
"end_offset": 5,
"type": "CN_WORD",
"position": 1
},
{
"token": "分词",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 2
},
{
"token": "器",
"start_offset": 4,
"end_offset": 5,
"type": "CN_CHAR",
"position": 3
},
{
"token": "后边",
"start_offset": 6,
"end_offset": 8,
"type": "CN_WORD",
"position": 4
},
{
"token": "是",
"start_offset": 8,
"end_offset": 9,
"type": "CN_CHAR",
"position": 5
},
{
"token": "测试",
"start_offset": 9,
"end_offset": 11,
"type": "CN_WORD",
"position": 6
},
{
"token": "内容",
"start_offset": 11,
"end_offset": 13,
"type": "CN_WORD",
"position": 7
},
{
"token": "spring",
"start_offset": 14,
"end_offset": 20,
"type": "ENGLISH",
"position": 8
},
{
"token": "cloud",
"start_offset": 21,
"end_offset": 26,
"type": "ENGLISH",
"position": 9
},
{
"token": "实战",
"start_offset": 26,
"end_offset": 28,
"type": "CN_WORD",
"position": 10
}
]
}
IK分词器有两种分词模式:ik_max_word和ik_smart模式。
1、ik_max_word:会将文本做最细粒度的拆分,比如会将"中华人民共和国人民大会堂"拆分为"中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。
2、ik_smart:会做最粗粒度的拆分,比如会将"中华人民共和国人民大会堂"拆分为中华人民共和国、人民大会堂。
// 测试两种分词模式
// ik_max_word模式
// 发送Post请求:http://localhost:9200/_analyze
// 发送的数据为:
{
"text":"中华人民共和国人民大会堂",
"analyzer":"ik_max_word"
}
// 响应的数据为:
{
"tokens": [
{
"token": "中华人民共和国",
"start_offset": 0,
"end_offset": 7,
"type": "CN_WORD",
"position": 0
},
{
"token": "中华人民",
"start_offset": 0,
"end_offset": 4,
"type": "CN_WORD",
"position": 1
},
{
"token": "中华",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 2
},
{
"token": "华人",
"start_offset": 1,
"end_offset": 3,
"type": "CN_WORD",
"position": 3
},
{
"token": "人民共和国",
"start_offset": 2,
"end_offset": 7,
"type": "CN_WORD",
"position": 4
},
{
"token": "人民",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 5
},
{
"token": "共和国",
"start_offset": 4,
"end_offset": 7,
"type": "CN_WORD",
"position": 6
},
{
"token": "共和",
"start_offset": 4,
"end_offset": 6,
"type": "CN_WORD",
"position": 7
},
{
"token": "国人",
"start_offset": 6,
"end_offset": 8,
"type": "CN_WORD",
"position": 8
},
{
"token": "人民大会堂",
"start_offset": 7,
"end_offset": 12,
"type": "CN_WORD",
"position": 9
},
{
"token": "人民大会",
"start_offset": 7,
"end_offset": 11,
"type": "CN_WORD",
"position": 10
},
{
"token": "人民",
"start_offset": 7,
"end_offset": 9,
"type": "CN_WORD",
"position": 11
},
{
"token": "大会堂",
"start_offset": 9,
"end_offset": 12,
"type": "CN_WORD",
"position": 12
},
{
"token": "大会",
"start_offset": 9,
"end_offset": 11,
"type": "CN_WORD",
"position": 13
},
{
"token": "会堂",
"start_offset": 10,
"end_offset": 12,
"type": "CN_WORD",
"position": 14
}
]
}
// ik_smart模式
// 发送Post请求:http://localhost:9200/_analyze
// 发送的数据为:
{
"text":"中华人民共和国人民大会堂",
"analyzer":"ik_smart"
}
// 响应的数据为:
{
"tokens": [
{
"token": "中华人民共和国",
"start_offset": 0,
"end_offset": 7,
"type": "CN_WORD",
"position": 0
},
{
"token": "人民大会堂",
"start_offset": 7,
"end_offset": 12,
"type": "CN_WORD",
"position": 1
}
]
}
如果要让分词器支持一些专有词语,可以自定义词库。IK分词器自带一个main.dic的文件,此文件为词库文件。
在上边的目录中新建一个my.dic文件(注意文件格式为utf-8)可按照main.dic的格式自定义词汇,并在IKAnalyzer.cfg.xml文件中配置my.dic文件,重启ES。
// my.dic文件内容
李哲龙
海贼王
// 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">my.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
可看见原来把 李哲龙 拆分成三个词的,现在合并成为一个词了。
// 发送Post请求:http://localhost:9200/_analyze
// 发送的数据为:
{
"text":"李哲龙",
"analyzer":"ik_max_word"
}
// 响应的数据为:
{
"tokens": [
{
"token": "李哲龙",
"start_offset": 0,
"end_offset": 3,
"type": "CN_WORD",
"position": 0
}
]
}
1、查询所有索引的映射:发送Get请求:http://localhost:9200/_mapping
// 返回的数据为:
{
"xc_course": {
"mappings": {
"doc": {
"properties": {
"description": {
"type": "text"
},
"name": {
"type": "text"
},
"studymodel": {
"type": "keyword"
}
}
}
}
}
}
2、创建映射:发送Post请求:http://localhost:9200/xc_course/doc/_mapping
// 请求的数据为:
{
"properties":{
"name":{
"type":"text"
},
"description":{
"type":"text"
},
"studymodel":{
"type":"keyword"
}
}
}
// 返回的数据为:
{
"acknowledged": true
}
3、更新映射:映射创建成功可以添加新字段,已有字段的类型不允许更新。除非把整个索引库全部删除,重建。
// 如果把description的字段类型从keyword变为text,不会成功
// 已有字段的类型修改时,会报错误的信息为:
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "mapper [studymodel] of different type, current_type [text], merged_type [keyword]"
}
],
"type": "illegal_argument_exception",
"reason": "mapper [studymodel] of different type, current_type [text], merged_type [keyword]"
},
"status": 400
}
4、删除映射:通过删除索引来删除映射,发送Delete请求:http://localhost:9200/xc_course
字符串类型有text和keyword类型;日期有date类型;数值有long,integer,short,float,byte,double,half_float,scaled_float;
1)analyzer:通过analyzer属性指定分词器。
下边指定name的字段类型为text,使用IK分词器的ik_max_word分词模式。
{
"name": {
"type": "text",
"analyzer": "ik_max_word"
}
}
上边指定了analyzer是指在索引和搜索都使用ik_max_word,如果单独想定义搜索时使用的分词器则可以通过search_analyzer属性。对于IK分词器建议是索引时使用ik_max_word将搜索内容进行细粒度分词,搜索时使用ik_smart提高搜索精确性。
{
"name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
}
}
2)index:通过index属性指定是否索引。
默认为index=true,即要进行索引,只有进行索引才可以从索引库搜索到。但是也有一些内容不需要索引,比如:商品图片地址只被用来展示图片,不进行搜索图片,此时可以将index设置为false。
// 删除索引,重新创建映射,将pic的index设置为false,尝试根据pic去搜索,结果搜索不到数据
{
"pic": {
"type": "text",
"index": false
}
}
3)store:是否在source之外存储。每个文档索引后会在 ES中保存一份原始文档,存放_source
在中,一般情况下不需要设置store为true,因为在_source中已经有一份原始文档了。
4)完整的例子:
删除xc_course索引库:Delete:http://localhost:9200/xc_course
// 响应的数据为:
{
"acknowledged": true
}
创建新的xc_course索引库:Put:http://localhost:9200/xc_course
// 设置的数据为:
{
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas":0
}
}
}
// 响应的数据为:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "xc_course"
}
创建新映射:Post或Put:http://localhost:9200/xc_course/doc/_mapping
// 创建映射添加的数据为:
{
"properties":{
"name":{
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
},
"description":{
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
},
"pic":{
"type":"text",
"index":false
},
"studymodel":{
"type":"text"
}
}
}
// 响应的数据为:
{
"acknowledged": true
}
插入文档:Post或Put:http://localhost:9200/xc_course/doc/4028e58161bcf7f40161bcf8b77c0000
// 插入的文档数据为:
{
"name": "Bootstrap开发框架",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"pic": "group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"studymodel": "201002"
}
// 响应的数据为:
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0000",
"_version": 1,
"result": "created",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
查询测试:
Get http://localhost:9200/xc_course/_search?q=name:开发
{
"took": 35,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0000",
"_score": 0.2876821,
"_source": {
"name": "Bootstrap开发框架",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"pic": "group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"studymodel": "201002"
}
}
]
}
}
Get http://localhost:9200/xc_course/_search?q=description:开发
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.48957998,
"hits": [
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0000",
"_score": 0.48957998,
"_source": {
"name": "Bootstrap开发框架",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"pic": "group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"studymodel": "201002"
}
}
]
}
}
Get http://localhost:9200/xc_course/_search?q=pic:group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg
// 由于pic的index为false,所以不能搜索到数据
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
Get http://localhost:9200/xc_course/_search?q=studymodel:201002
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0000",
"_score": 0.2876821,
"_source": {
"name": "Bootstrap开发框架",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"pic": "group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"studymodel": "201002"
}
}
]
}
}
通过测试发现:name和description都支持全文检索,pic不可作为查询条件。
上边介绍的text文本字段在映射时要设置分词器,keyword字段为关键字字段,通常搜索keyword是按照整体搜索,所以创建keyword字段的索引时是不进行分词的,比如:邮政编码、手机号码、身份证等。keyword字段通常用于过虑、排序、聚合等。
测试:
更改映射,Put/Post请求:http://localhost:9200/xc_course/doc/_mapping
// 发送的数据为:
{
"properties": {
"name": {
"type": "keyword"
},
"description": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"pic": {
"type": "text",
"index": false
},
"studymodel": {
"type": "keyword"
}
}
}
// 返回的数据为:
{
"acknowledged": true
}
插入文档:Post/Put请求:http://localhost:9200/xc_course/doc/4028e58161bcf7f40161bcf8b77c0000
// 请求的数据为:
{
"name": "Bootstrap开发框架",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"pic": "group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"studymodel": "201002"
}
// 返回的数据为:
{
"_index": "xc_course",
"_type": "doc",
"_id": "4028e58161bcf7f40161bcf8b77c0000",
"_version": 1,
"result": "created",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
根据studymodel查询文档,搜索:Get:http://localhost:9200/xc_course/_search?q=name:java
// 返回的数据为:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 0,
"max_score": null,
"hits": []
}
}
name是keyword类型,所以查询方式是精确查询。
日期类型不用设置分词器。通常日期类型的字段用于排序。format:通过format设置日期格式
下边的设置允许date字段存储年月日时分秒、年月日及毫秒三种格式。
// 在插入索引的时候:指定日期类型
// Put/Post请求:http://localhost:9200/xc_course/doc/_mapping
{
"properties": {
"name": {
"type": "keyword"
},
"description": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"pic": {
"type": "text",
"index": false
},
"studymodel": {
"type": "keyword"
},
"timestamp": {
"type": "date",
"format": "yyyy‐MM‐dd HH:mm:ss||yyyy‐MM‐dd||epoch_millis"
}
}
}
// 插入文档:Post/Put请求:http://localhost:9200/xc_course/doc/3
{
"name": "spring开发基础",
"description": "spring 在java领域非常流行,java程序员都在用。",
"studymodel": "201001",
"pic": "group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"timestamp": "2018‐07‐04 18:28:58"
}
ES支持的数据类型为:long,integer,short,float,byte,double,half_float,scaled_float;
选择数据类型的建议:
1、尽量选择范围小的类型,提高搜索效率
2、对于浮点数尽量用比例因子,比如一个价格字段,单位为元,我们将比例因子设置为100这在ES中会按分存 储,映射如下:
"price": { "type": "scaled_float", "scaling_factor": 100 }
由于比例因子为100,如果我们输入的价格是23.45则ES中会将23.45乘以100存储在ES中。如果输入的价格是23.456,ES会将23.456乘以100再取一个接近原始值的数,得出2346。使用比例因子的好处是整型比浮点型更易压缩,节省磁盘空间。
3、如果比例因子不适合,则从下表选择范围小的去用:
Type | Minimum value | Maximum value | Significant bits / digits |
---|---|---|---|
double | 2^-1074 | (2-2^-52)*2^1023 | 53 / 15.95 |
float | 2^-149 | (2-2^-23)*2^127 | 24 / 7.22 |
half_float | 2^-24 | 65504 | 11 / 3.31 |
4、测试例子:
// 更新已有映射,Post请求:localhost:9200/xc_course/doc/_mapping,发送的数据为:
{
"properties": {
"name": {
"type": "keyword"
},
"description": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"pic": {
"type": "text",
"index": false
},
"studymodel": {
"type": "keyword"
},
"timestamp": {
"type": "date",
"format": "yyyy‐MM‐dd HH:mm:ss||yyyy‐MM‐dd"
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
// 并插入文档:Post请求:http://localhost:9200/xc_course/doc/3,发送的数据为:
{
"name": "spring开发基础",
"description": "spring 在java领域非常流行,java程序员都在用。",
"studymodel": "201001",
"pic": "group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"timestamp": "2018‐07‐04 18:28:58",
"price": 38.6
}
// 查询文档数据:Get请求:http://localhost:9200/xc_course/doc/3,返回的数据为:
{
"_index": "xc_course",
"_type": "doc",
"_id": "3",
"_version": 2,
"found": true,
"_source": {
"name": "spring开发基础",
"description": "spring 在java领域非常流行,java程序员都在用。",
"studymodel": "201001",
"pic": "group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"timestamp": "2018‐07‐04 18:28:58",
"price": 38.6
}
}
创建如下映射:Post:http://localhost:9200/xc_course/doc/_mapping
{
"properties": {
"description": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"pic": {
"type": "text",
"index": false
},
"price": {
"type": "float"
},
"studymodel": {
"type": "keyword"
},
"timestamp": {
"type": "date",
"format": "yyyy‐MM‐dd HH:mm:ss||yyyy‐MM‐dd||epoch_millis"
}
}
}
插入文档:Post请求:http://localhost:9200/xc_course/doc/1
{
"name": "Bootstrap开发",
"description": "Bootstrap是由Twitter 推出的一个前台页面开发框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量 的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的精 美界面效果。",
"studymodel": "201002",
"price": 38.6,
"timestamp": "2018-04-25 19:11:35",
"pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}
DSL(Domain Specifific Language)是ES提出的基于json的搜索方式,在搜索时传入特定的json格式的数据来完成不同的搜索需求。DSL比URI搜索方式功能强大,在项目中建议使用DSL方式来完成搜索。
查询所有索引库的文档: 发送Post请求:http://localhost:9200/_search
查询指定索引库指定类型下的文档:
发送Post请求:http://localhost:9200/xc_course/doc/_search
// 请求的数据为:
{
"query": {
"match_all": {}
},
"_source": [
"name",
"studymodel"
]
}
// 返回的数据为:
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1.0,
"hits": [
{
"_index": "xc_course",
"_type": "doc",
"_id": "1",
"_score": 1.0,
"_source": {
"studymodel": "201002",
"name": "Bootstrap开发"
}
},
{
"_index": "xc_course",
"_type": "doc",
"_id": "2",
"_score": 1.0,
"_source": {
"studymodel": "201001",
"name": "java编程基础"
}
},
{
"_index": "xc_course",
"_type": "doc",
"_id": "3",
"_score": 1.0,
"_source": {
"studymodel": "201001",
"name": "spring开发基础"
}
}
]
}
}
_source:source源过虑设置,指定结果中所包括的字段有哪些。
结果说明:
took:本次操作花费的时间,单位为毫秒。
timed_out:请求是否超时
_shards:说明本次操作共搜索了哪些分片
hits:搜索命中的记录
hits.total : 符合条件的文档总数
hits.hits :匹配度较高的前N个文档
hits.max_score:文档匹配得分,这里为最高分
_score:每个文档都有一个匹配度得分,按照降序排列。
_source:显示了文档的原始内容。
ES支持分页查询,传入两个参数:from和size。
from:表示起始文档的下标,从0开始。size:查询的文档数量。
发送Post请求:http://localhost:9200/xc_course/doc/_search
// 请求的数据为:
{
"from": 0,
"size": 1,
"query": {
"match_all": {}
},
"_source": [
"name",
"studymodel"
]
}
Term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。
发送Post请求:http://localhost:9200/xc_course/doc/_search
// 请求的数据为:
{
"query": {
"term": {
"name": "spring开发"
}
},
"_source": [
"name",
"studymodel"
]
}
// 不会将name进行分词,所以name中必须全部包含spring开发的才能被搜索到
ES提供根据多个id值匹配的方法:
发送Post请求:http://127.0.0.1:9200/xc_course/doc/_search
// 请求的数据为:
{
"query": {
"ids": {
"type": "doc",
"values": [
"3",
"4",
"100"
]
}
}
}
1、基本使用
Match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。
Match query与Term query区别是Match Query在搜索前先将搜索关键字分词,再拿各各词语去索引中搜索。
发送Post请求:http://localhost:9200/xc_course/doc/_search
// 请求的数据为:
{
"query": {
"match": {
"description": {
"query": "spring开发",
"operator": "or"
}
}
}
}
query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用 逗号分隔也可以不用。
operator:or表示:只要有一个词在文档中出现则就符合条件,and表示:每个词都在文档中出现则才符合条件。
上边的搜索的执行过程是:
1)将"spring开发"分词,分为spring、开发两个词
2)再使用spring和开发两个词去匹配索引中搜索。
3)由于设置了operator为or,只要有一个词匹配成功则就返回该文档。
2、minimum_should_match
上边使用的operator = or表示只要有一个词匹配上就得分,如果实现三个词至少有两个词匹配如何实现?
使用minimum_should_match可以指定文档匹配词的占比:
比如搜索语句如下:
{
"query": {
"match": {
"description": {
"query": "spring开发框架",
"minimum_should_match": "80%"
}
}
}
}
"spring开发框架"会被分为三个词:spring、开发、框架
设置"minimum_should_match": "80%"表示,三个词在文档的匹配占比为80%,即3*0.8=2.4,向上取整得2,表 示至少有两个词在文档中要匹配成功。
上边学习的termQuery和matchQuery一次只能匹配一个Field,本节学习multiQuery,一次可以匹配多个字段。
1、基本使用
单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配。
发送Post请求:http://localhost:9200/xc_course/doc/_search
拿关键字 "spring css"去匹配name和description字段。
{
"query": {
"multi_match": {
"query": "spring css",
"minimum_should_match": "50%",
"fields": [
"name",
"description"
]
}
}
}
2、提升boost
匹配多个字段时可以提升字段的boost(权重)来提高得分
提升boost之前,执行上边的查询,通过查询发现Bootstrap排在前边;提升boost,通常关键字匹配上name的权重要比匹配上description的权重高,这里可以对name的权重提升。
{
"query": {
"multi_match": {
"query": "spring框架",
"minimum_should_match": "50%",
"fields": [
"name^10",
"description"
]
}
}
}
"name^10" 表示权重提升10倍,执行上边的查询,发现name中包括spring关键字的文档排在前边。
布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来。
三个参数:
must:文档必须匹配must所包括的查询条件,相当于 "AND"
should:文档应该匹配should所包括的查询条件其中的一个或多个,相当于"OR"
must_not:文档不能匹配must_not所包括的该查询条件,相当于"NOT"
{
"_source": [
"name",
"studymodel",
"description"
],
"from": 0,
"size": 1,
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "spring框架",
"minimum_should_match": "50%",
"fields": [
"name^10",
"description"
]
}
},
{
"term": {
"studymodel": "201001"
}
}
]
}
}
}
过滤是针对搜索的结果进行过滤,过滤器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过滤器性能比查询要高,且方便缓存,推荐尽量使用过滤器去实现查询或者过滤器和查询共同使用。 过滤器只在布尔查询中使用。
{
"_source": [
"name",
"studymodel",
"description",
"price"
],
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "spring框架",
"minimum_should_match": "50%",
"fields": [
"name^10",
"description"
]
}
}
],
"filter": [
{
"term": {
"studymodel": "201001"
}
},
{
"range": {
"price": {
"gte": 60,
"lte": 100
}
}
}
]
}
}
}
range:范围过虑,保留大于等于60 并且小于等于100的记录。
term:项匹配过虑,保留studymodel等于"201001"的记录。
注意:range和term一次只能对一个Field设置范围过虑。
可以在字段上添加一个或多个排序,支持在keyword、date、float等类型上添加,text类型的字段上不允许添加排序。
// 过滤0--10元价格范围的文档,并且对结果进行排序,先按studymodel降序,再按价格升序
{
"_source": [
"name",
"studymodel",
"description",
"price"
],
"query": {
"bool": {
"filter": [
{
"range": {
"price": {
"gte": 0,
"lte": 100
}
}
}
]
}
},
"sort": [
{
"studymodel": "desc"
},
{
"price": "asc"
}
]
}
高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。
在搜索语句中添加highlight即可实现,如下:
{
"_source": [
"name",
"studymodel",
"description",
"price"
],
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "开发框架",
"minimum_should_match": "50%",
"fields": [
"name^10",
"description"
],
"type": "best_fields"
}
}
],
"filter": [
{
"range": {
"price": {
"gte": 0,
"lte": 100
}
}
}
]
}
},
"sort": [
{
"price": "asc"
}
],
"highlight": {
"pre_tags": [
"<tag>"
],
"post_tags": [
"</tag>"
],
"fields": {
"name": {},
"description": {}
}
}
}
ES通常以集群方式工作,这样做不仅能够提高 ES的搜索能力还可以处理大数据搜索的能力,同时也增加了系统的 容错能力及高可用,ES可以实现PB级数据的搜索。
1)结点
ES集群由多个服务器组成,每个服务器即为一个Node结点(该服务只部署了一个ES进程)。
2)分片
当我们的文档量很大时,由于内存和硬盘的限制,同时也为了提高ES的处理能力、容错能力及高可用能力,我们将索引分成若干分片,每个分片可以放在不同的服务器,这样就实现了多个服务器共同对外提供索引及搜索服务。 一个搜索请求过来,会分别从各各分片去查询,最后将查询到的数据合并返回给用户。
3)副本
为了提高ES的高可用同时也为了提高搜索的吞吐量,我们将分片复制一份或多份存储在其它的服务器,这样即使当前的服务器挂掉了,拥有副本的服务器照常可以提供服务。
4)主结点
一个集群中会有一个或多个主结点,主结点的作用是集群管理,比如增加节点,移除节点等,主结点挂掉后ES会重新选一个主结点。
5)结点转发
每个结点都知道其它结点的信息,我们可以对任意一个结点发起请求,接收请求的结点会转发给其它结点查询数 据。
主结点:master节点主要用于集群的管理及索引 比如新增结点、分片分配、索引的新增和删除等。
数据结点:data节点上保存了数据分片,它负责索引和搜索操作。
客户端结点:client节点仅作为请求客户端存在,client的作用也作为负载均衡器,client节点不存数据,只是将请求均衡转发到其它结点。
通过下边两项参数来配置结点的功能:
node.master: #是否允许为主结点
node.data: #允许存储数据作为数据结点
node.ingest: #是否允许成为协调节点,
四种组合方式:
master=true,data=true:即是主结点又是数据结点
master=false,data=true:仅是数据结点
master=true,data=false:仅是主结点,不存储数据
master=false,data=false:即不是主结点也不是数据结点,此时可设置ingest为true表示它是一个客户端。
下边的例子实现创建一个2结点的集群,并且索引的分片我们设置2片,每片一个副本。
1)创建节点1
解压elasticsearch-6.2.1.zip 到 F:/elasticsearch/elasticsearch-1
节点1对外服务的http端口是:9200,集群管理端口是9300,配置elasticsearch.yml,结点名:xc_node_1
elasticsearch.yml内容如下:
cluster.name: xuecheng
node.name: xc_node_1
network.host: 0.0.0.0
http.port: 9200
transport.tcp.port: 9300
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["0.0.0.0:9300", "0.0.0.0:9301"]
discovery.zen.minimum_master_nodes: 1
node.ingest: true
node.max_local_storage_nodes: 2
path.data: F:\elasticsearch\elasticsearch-1\data
path.logs: F:\elasticsearch\elasticsearch-1\logs
http.cors.enabled: true
http.cors.allow‐origin: /.*/
进入bin目录,运行bat脚本,启动节点1。
2)创建节点2
解压elasticsearch-6.2.1.zip 到 F:/elasticsearch/elasticsearch-2
节点2对外服务的http端口是:9201,集群管理端口是9301,配置elasticsearch.yml,结点名:xc_node_2
elasticsearch.yml内容如下:
cluster.name: xuecheng
node.name: xc_node_2
network.host: 0.0.0.0
http.port: 9201
transport.tcp.port: 9301
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["0.0.0.0:9300", "0.0.0.0:9301"]
discovery.zen.minimum_master_nodes: 1
node.ingest: true
node.max_local_storage_nodes: 2
path.data: F:\elasticsearch\elasticsearch-2\data
path.logs: F:\elasticsearch\elasticsearch-2\logs
http.cors.enabled: true
http.cors.allow‐origin: /.*/
进入bin目录,运行bat脚本,启动节点1。
3)创建索引库
// 使用Put请求:http://localhost:9200/xc_test
// 创建2分片,1个副本;发送的数据为:
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1
}
}
通过Get请求:/_cluster/health 来查看Elasticsearch的集群健康情况。
用三种颜色来展示健康状态:green、yellow或者red。green:所有的主分片和副本分片都正常运行。yellow:所有的主分片都正常运行,但有些副本分片运行不正常。red:存在主分片运行不正常。
Get请求:http://localhost:9200/_cluster/health
// 响应的数据为:
{
"cluster_name": "xuecheng",
"status": "green",
"timed_out": false,
"number_of_nodes": 2,
"number_of_data_nodes": 2,
"active_primary_shards": 2,
"active_shards": 4,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 100.0
}