Elasticsearch下载
地址如下:
https://www.elastic.co/cn/downloads/elasticsearch
Elasticsearch安装head插件
下载elasticsearch-head-master.zip包:https://github.com/mobz/elasticsearch-head
配置与启动
启动elasticsearch-head-master插件,前提是电脑需要安装node.js 具体哪请参考(): elasticsearch-head-master的目录下,打开cmd.执行如下命令:
npm run start
先启动主节点:
打开文件下面的config的:elasticsearch.yml 文件 如果要配置分节点建议每个分节点从压缩包重新解压。
http.cors.enabled: true
http.cors.allow-origin: "*"
cluster.name: wali
node.name: master
node.master: true
network.host: 127.0.0.1
启动为bin文件里面的 elasticsearch-bat 文件 ,后台启动的时候 elasticsearch.bat-d
在启动从节点1:
cluster.name: wali//这里需要和主节点保持一致
node.name: slave1
network.host: 127.0.0.1
http.port: 8200
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
在启动从节点2
cluster.name: wali//这里需要和主节点保持一致
node.name: slave2
network.host: 127.0.0.1
http.port: 8000
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
基础概念
1、索引(Index)、类型(Type)、文档(Document)
- 索引是含有相同属性的文档集合。索引在ES中是通过一个名字来识别的,且必须是英文字母小写,且不含中划线(-);可类比于 MySQL 中的 database ;但是,后文会提到,在 7.0中,由于类型(Type)的移除,我们可以理解为,一个索引就是一张 table。
- 一个索引中可以定义一个或多个类型,文档必须属于一个类型;可类比于 MySQL 中的 table;
- 档是可以被索引的基本数据单位。文档是Elasticsearch中最小的数据存储单位。可类比于 MySQL 中 一个table 中的一行记录。
注意事项:
从ES6.0开始,官方便不建议一个索引中创建多个类型;在ES7.0中,更是移除了类型(Type)这个概念。
2、分片、备份
- 在ES中,每个索引都有多个分片,每个分片都是一个Lucene索引。假设一个索引的数据量很大,就会造成硬盘压力很大,同时,搜索速度也会出现瓶颈。我们可以将一个索引分为多个分片,从而分摊压力;分片同时还允许用户进行水平地扩展和拆分,以及分布式的操作,可以提高搜索以及其他操作的效率。
- 拷贝一份分片,就完成了分片的备份。备份的好处是,当一个主分片出现问题时,备份的分片就能代替工作,从而提高了ES的可用性。同时,备份的分片还可以执行搜索操作,以分摊搜索的压力。
基础操作
ES的API组成结构
ES提供了一系列RESTFul风格的API供我们对ES数据进行操作。下面是它的基本格式:
http://<ip>:<port>/<索引>/_doc/<文档ID> // Type 字段那里变为固定值 _doc
需要执行的动作,由请求方式决定。下面是常见的请求方式,具体意义后面会详细讲:
GET/POST/PUT/DELETE/HEAD
创建索引
1、第一种方式,直接在head插件上创建索引。
在这里插入图片描述
如上图所示,概览页也出现了变化。图中的所有方框都是ES索引的分片,边框加粗的就是主分片,而未加粗就是分片的备份;比如:边框不加粗的0号分片就是 0号主分片的备份。
这样创建索引,是进行了一次 非结构化创建。什么意思呢,类比 我们创建一个数据库,但是没有创建任何表、也没有任何表结构。简而言之,就是我们创建了一个没有任何数据结构的索引。
如何确定一个索引是结构化还是非结构化的呢?
如上图,我们点击 概览-信息-索引信息,在弹出的窗口中找到 mappings 项,其值是空的,就代码该索引是非结构化的。那么,如何将其修改为结构化的呢?也就是说,我们需要为book索引构建出数据结构(类比于,为book表构建出表结构)。
我们在 head 插件上点击 复合查询 - 查询,然后在这个模块中输入图示的信息,勾选 已读 ,然后点击 验证JSON,JSON内容便会格式化为已读的状态;然后点击 提交请求 ,操作成功后,右侧便会显式提示信息,如下图:
此时,我们点击 概览 - 刷新,然后选择 book 索引的 信息 - 索引信息,就可以在弹出窗口中查看到 book 索引的文档数据结构:
2、第二种方式,使用 PostMan 等第三方HTTP客户,通过ES RestFul API来创建索引。
这里,我使用的POSTMAN工具。
首先,我们创建一个新的 people 索引。在http文件中输入:
创建一个新的 people 索引,注意,将IP替换为你们自己的主机地址
PUT http://10.247.63.97:9200/people
Content-Type: application/json
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"type": {"type": "keyword"},
"name": {"type": "text"},
"country": {"type": "keyword"},
"age": {"type": "integer"},
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
}
}
}
}
这里,解释一下上面JSON内容的意思:
- settings字段:用于指定我们索引的配置
- number_of_shards:指定当前索引的分片数
- number_of_replicas:指定当前索引的备份数
- mappings字段:指定索引的数据映射定义:
- properties:指定索引的属性定义;这里,这里,定义了 5 个字段,分别为 type、name、country、age、date;需要注意的是,这里的type,这是一个字段,和我们上文中提到的在7.0中移除了的类型(Type)并不是同一个东西;官方推荐我们的是,如果我们有 类型(Type)定义 这个需求,我们可以在字段中自定义一个字段,用来标识当前 document 属于哪个Type;这里,我们就使用这个名为 “type” 字段(可以按照自己的习惯自定义名称),来标识当前文档属于哪个 Type;
- 后面的 {“type” : “integer”}、{“type” : “text”}分别表示当前字段数据的类型为 整数、文本,以及
关键字(keyword)、日期类型等。 - date字段中,我们可以为其指定匹配多种格式,使用 || 分隔;
请求完毕后,若索引创建成功,则会看到如下输出:
这时,我们再去head插件中确认一下,点击 刷新 按钮,即可看到我们刚刚新创建的people索引:
查看 people 的索引信息,我们可以看到 people 索引存储数据的结构:
数据插入
在ES中,数据插入又分为两种:
- 指定文档ID插入:手动指定ID
- 自动产生文档ID插入:不是MySQL那样的AutoIncrement,而是类似MongoDB那样的自动生成ID
指定文档ID插入:
在刚刚的http文件中,使用 ### (三个#号)将请求分隔开,在下面输入:
//向 people索引中插入一条 指定ID的数据,注意请求方式为 PUT
//路径格式为 http://<ip>:<port>/<索引>/_doc/<文档ID>,下面我们插入了一条 ID 为 1 的数据
PUT http://10.247.63.97:9200/people/_doc/1
Content-Type: application/json
{
"type": "man",
"name": "Zereao",
"country": "China",
"age": "23",
"date": "1995-11-27"
}
然后执行,可以看到下面的输出:
自动生成ID插入:
// 向 people索引中插入一条 自动生成ID的数据,注意,请求方式为 POST,并删除URL末尾的 ID
POST http://10.247.63.97:9200/people/_doc/
Content-Type: application/json
{
"type": "man",
"name": "AutoZereao",
"country": "China",
"age": "23",
"date": "1995-11-27 12:25:35"
}
输出结构这里我就不贴了。上面我们分别插入了两条数据,一条是手动指定ID,PUT请求方式;一条是自动生成ID,POST请求方式。我们可以从Head插件上查看到我们刚刚插入的数据:点击 数据浏览,选中 people索引,即可查看数据:
直接修改文档:
修改 ID 为 1 的文档的 name 字段值为 UpdateZereao,格式:{index}/_update/{id}
POST http://10.247.63.97:9200/people/_update/1/
Content-Type: application/json
{
"doc": {
"name": "UpdateZereao"
}
}
运行后,我们可以通过Head插件查看更改,点击 更新 后,我们可以看到数据:
删除操作
这里呢,我主要讲两个删除操作:
1、文档删除
2、索引删除
删除people索引中,ID为1的文档:
删除 people索引中 ID = 1 的文档
DELETE http://10.247.63.97:9200/people/_doc/1/
Content-Type: application/json
输出结果这里我就不贴了,可以打开head插件,刷新数据后,我们便可以看到,people 索引中ID为1的文档已经被删除成功了。
第二种方式,通过RestFul API:
删除 people 索引
DELETE http://10.247.63.97:9200/people
Content-Type: application/json
点击运行,我们就可以将 people 索引删除掉。删除成功后,我们可以从 head 插件中看到索引已经被删除了。
需要注意的是,删除一个索引后,该索引下的所有数据,包括所有类型和文档,都会被删除。对于删除操作,我们要万分小心。
查询操作
ES的查询可以分为简单查询、条件查询、聚合查询。
首先,我们先造一批数据。首先新建一个 book 索引,然后指定ID插入多条文档。具体语句这里不给出,在文末的附件中的es_book.http文件中,我会给出我插入数据的语句,总共插入了12条文档记录。有需要的同学可以去下载。
简单查询:
简单查询,查询 book 索引中,ID为1 的文档
GET http://10.247.63.97:9200/book/_doc/1
Content-Type: application/json
条件查询:
查询book索引中的所有数据:
条件查询,查询所有数据
POST http://10.247.63.97:9200/book/_search
Content-Type: application/json
{
"query": {
"match_all": {}
}
}
这里,查询结果我就不贴出来了。值得一提的是,最外层的hits 字段下就是我们查出来的数据;hits字段下的total字段代表记录总条数;hits字段下还有一个 hits json数组,这就是查出的每一条记录的详情。默认情况下,只查出10条,hits json数组的大小为10,这个我们可以通过 from 、size 属性手动指定返回哪些数据:
条件查询,指定返回数据大小以及从哪里开始返回
POST http://10.247.63.97:9200/book/_search
Content-Type: application/json
{
"query": {
"match_all": {}
},
"from": 1,
"size": 1
}
关键词匹配:
条件查询,查询标题中包含 传 字的文档
POST http://10.247.63.97:9200/book/_search
Content-Type: application/json
{
"query": {
"match": {
"title": "传"
}
}
}
这里,将会查出两条数据。默认情况下,查询出的结果 hits json数组中的数据,是按照_score字段的值大小倒序排序的。我们也可以指定排序方式:
条件查询,指定排序方式为 按照 publish_date 降序 排序
POST http://10.247.63.97:9200/book/_search
Content-Type: application/json
{
"query": {
"match": {
"title": "传"
}
},
"sort": [
{
"publish_date": {
"order": "desc"
}
}
]
}
聚合查询:
单个分组聚合:
聚合查询,按照 这一批 book 的字数进行聚合; 这是一个单个分组聚合
POST http://10.247.63.97:9200/book/_search Content-Type: application/json
{
"aggs": {
"group_by_word_count": {
"terms": {
"field": "word_count"
}
}
}
}
注意,上面的 group_by_word_count 表示该聚合的名称,是自定义的,可以自己为该聚合命名。
多个分组聚合:
聚合查询,按照 这一批 book 的字数和出版日期进行聚合; 这是一个多个分组聚合
POST http://10.247.63.97:9200/book/_search
Content-Type: application/json
{
"aggs": {
"group_by_word_count": {
"terms": {
"field": "word_count"
}
},
"group_by_publish_date": {
"terms": {
"field": "publish_date"
}
}
}
}
计算某一字段的数据:
聚合查询,计算 word_count 字段的相关数据
POST http://10.247.63.97:9200/book/_search
Content-Type: application/json
{
"aggs": {
"grades_word_count": {
"stats": {
"field": "word_count"
}
}
}
}
这里,grades_word_count也是可以自定义的,stats表示对字段值进行计算。执行后,我们可以得到一段这样的数据:
如图,上面计算除了 word_count 字段的 最大值、最小值、均值、数量、总和等数据。
至此,我们Elasticsearch基础概念与基本操作就介绍完毕了。
参考文档
1、https://www.imooc.com/learn/889
2、https://www.elastic.co/guide/en/elasticsearch/reference/current/glossary.html
3、https://www.elastic.co/guide/en/elasticsearch/reference/current/removal-of-types.html
5、https://elasticsearch.cn/article/601