一、简介
- Elasticsearch和MongoDB/Redis类似,是非关系型数据库,从索引文档到文档能被搜索到只有一个轻微的延迟,是采用Restful API标准的可扩展和高可用的实时数据分析的全文搜索工具
- Elastic Search的实现原理是,利用内置分词器(Analyzer)对数据库文本进行分词,将解析出的关键词和数据库文档建立倒排索引。输入的搜索文本也会进行分词,通过倒排索引找到匹配的数据库文本。之后使用 TF-IDF算法,根据相关度对每个匹配的文本进行评分排序,返回搜索结果。
二、ES数据库特性
- 可拓展:支持一主多从且扩容简易,只要cluster.name一致且在同一个网络中就能自动加入当前集群;本身就是开源软件,也支持很多开源的第三方插件
- 高可用:在一个集群(Cluster)多个节点(Node)中分布式存储,索引(Index)支持分片(Shards)和复制(Replicas),即使部分节点down掉,也能自动进行数据恢复和主从切换
- 采用RestfulAPI标准:通过http接口使用JSON格式进行操作数据;数据存储的最小单位是文档,本质上是一个JSON 文本
三、与关系型数据库的区别
- 索引 Index:一个拥有几分相似特征的文档的集合
- 类型 Type:索引可以为拥有相同字段的文档定义一个类型;个索引中可以创建多个Type
- 文档 Document:一个文档是一个可被索引的基础信息单元
- 字段 Field:Elasticsearch的最小单位,相当于数据某一列
- 映射 Mapping:所有的文档在写进索引之前都需要进行分析,如何将输入的文本分隔为词条,哪些词条又会被过滤,这种行为叫做映射,一般由用户自己定义相应的规则
SQL数据库(MySQL) NoSQL数据库(ES) 数据库 Database 索引 Index 表 Table 类型 Type 数据行 Row 文档 Document 数据列 Column 字段 Field 四、ELK搭建
ELK = elasticsearch + logstash + kibana
ELK常作为大型分布式系统的日志分析收集处理的解决方案:
- ElasticSearch是一个基于Lucene基础上构建的开源搜索工具,具备实时性、分布式、可扩展等优点,并对Lucene进行了封装,开发者通过RESTful API即可实现对数据的搜索;
- logstash是一个用于日志搜集, 分析, 过滤的工具. client端一般部署在用于搜集日志的主机上, server端负责将接收的到日志进行过滤, 然后转发到elasticsearch上;
- kibana是一个用于汇总分析和搜索日志的工具, 可以为elasticsearch和logstash提供友好的日志分析的web界面;
在docker上搭建ELK,完成非关系型数据库的构建
- docker安装教程:Install Docker Engine on CentOS
- ELK搭建教程:基于腾讯云服务器安装ELK
常见问题
1. 生成注册令牌
连接 Kibana 实例或在安全的 Elasticsearch 集群中注册其他节点。
使用 elasticsearch-create-enrollment-token 工具创建注册令牌。
2. 页面数据查询报406错误
ES-Head需要Restful接口
{"error":"Content-Type header [application/x-www-form-urlencoded] is not supported","status":406}
解决方法:
- 进入docker容器
# 命令 docker exec -it 容器ID /bin/bash [root@localhost ~]# docker exec -it es-head /bin/bash
- cd进入_site/目录,编辑vendor.js
[root@localhost ~]# vim _site/vendor.js # 6886行: contentType: “application/x-www-form-urlencoded改成 # contentType: "application/json;charset=UTF-8" # 7573行: var inspectData = s.contentType === “application/x-www-form-urlencoded” && 改成 # var inspectData = s.contentType === "application/json;charset=UTF-8" &&
3. kibana Unable to connect to Elasticsearch at http://elasticsearch:9200
重启elk服务后,需要在kibana修改es的ip
解决方法:
- 进入docker容器
# 命令 docker exec -it 容器ID /bin/bash [root@localhost ~]# docker exec -it es-head /bin/bash
- kibana的配置文件出了问题,所以要修改配置文件,找到kibana.yml,进入修改
vim /etc/kibana/kibana.yml # 将elasticsearch改为自己的ip
- 重启kibana
五、ES基本操作
1. ES数据库建立
- 把所有字段设置为 "index": "not_analyzed"
- _source 打开,不用零散存储每个字段,更高效
- _all 关闭,因为检索是基于 k=v 这样字段已知的查询的
{ "properties":{ "属性": { "index": "not_analyzed", "type": "类型" } } "_source": { "enabled": true }, "_all": { "enabled": false } }
2. ES索引相关操作
添加索引
- 请求形式 PUT
- Content-Type: application/json
- URL: http://{ELK服务地址}:9200/{索引名称}
{ "settings":{ "index":{ "number_of_shards":"2", // 分片 "number_of_replicas":"0", // 副本数 } } }
删除索引
- 请求形式 DELETE
- Content-Type: application/json
- URL: http://{ELK服务地址}:9200/{索引名称}
3. ES文档相关操作
添加文档
- 请求形式 POST
- Content-Type: application/json
- URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/{id}
/* id不是必填项,如果不传,ES会给一个默认值 */
{ // 创建的文档数据内容 "属性1": "值1", "属性2": "值2", "属性3": "值3 ", "属性4": "值4" ...... }
更新文档(局部更新)
- 请求形式 POST
- Content-Type: application/json
- URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/{id}/_update
/* id是必填项 */
{ // 更新的局部数据内容 // doc作为键的数据json串 "doc": { "属性1": "值1", "属性2": "值2" ..... } }
删除文档
- 请求形式 DELETE
- Content-Type: application/json
- URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/{id}
/* id是必填项 */
查询文档
/* 简易查询 */ 请求形式 GET Content-Type: application/json /* 通过id查询,返回文档全部字段 */ URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/{id} /* 通过id查询,只返回文档特定字段 */ URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/{id}/_source?source=字段1,字段2 /* 全量查找,返回类型全部数据 */ URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 简易条件查询,返回类型中符合条件的文档 */ URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search?q=条件{字段: 值} /* DSL搜索 */ 请求形式 POST Content-Type: application/json URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 例如:查询年龄为34的用户数据 */ JSON { "query": { "match": { "age": 34 } } } /* 例如:查询年龄大于26岁且性别为男的用户数据 */ JSON { "query": { "bool": { "filter": { "range": { "age": { "gt": 26 } } }, "must": { "match": { "sex": "男" } } } } } /* 例如:查询名字为魏大勇和秀琴的用户信息 */ JSON { "query": { "match": { "name": "魏大勇 秀琴" } } } /* 查询结果高亮显示 */ /* 例如:查询名称为张三的用户数据 */ { "query": { "match": { "name": "张三" } }, "highlight": { "fields": { "name": {} } } } /* 聚合操作(类似分组操作)*/ /* 例如:查询各个年龄的用户数 */ { "aggs": { "all_interests": { "terms": { "field": "age.keyword" } } } }
4. 元数据操作
文档 (document) 的元数据(Metedata)
- _index
- document 存储在哪个 index 中
- 类似的文档(document)放在同一个 index ,不同类型的文档放在不同的 index
- index 名称必须小写,不用下划线(_)开头,不含逗号
- _type
- 代表 document 属于 index 下的哪个类型(type)
- 一个 index 通常包含多个 type
- type 名称可大小写,不用下划线(_)开头,不含逗号
- _id
- 代表 document 唯一标识,与index和type一起确定一个唯一的document
- id 生成方式
- 手动指定:PUT /index/type/id
- 自动生成: PUT /index/type/ (base64编码20长度字符串,分布式集群下不可能重复)
- _score
- 相关度分数:匹配程度,分数越高越相关
查询响应
返回结果做JSON格式化操作
- 请求形式 GET POST
- 参数:?pretty // url结尾加上参数
- URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/{id}?pretty
判断某个文档是否存在,不查询它的内容
- 请求形式 HEAD
- URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/{id}
- 返回: 200 OK; 404 Not Found
批量查询
/* 例如:查询id为1002和1003的文档数据 */ 请求形式 POST 参数:_mget // url结尾加上参数 URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_mget JSON { "ids":["1002","1003"] }
批量添加
请求形式 POST 参数:_bulk // url结尾加上参数 URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_bulk JSON // 注意:每条数据后需要加换行,最后一行也要加 {action:{metedata}}\n {source body}\n {action:{metedata}}\n {source body}\n ...... /* 例如:新增三条数据 */ {"create":{"_index":"{索引名称}","_type":"{类型}","_id":"{id_1}"}} {"id":"1006","name":"user001","age":20,"sex":"男"} {"create":{"_index":"{索引名称}","_type":"{类型}","_id":"{id_2}"}} {"id":"1007","name":"user002","age":30,"sex":"男"} {"create":{"_index":"{索引名称}","_type":"{类型}","_id":"{id_3}"}} {"id":"1008","name":"user003","age":40,"sex":"女"} /* 例如:批量删除三条数据 */ {"delete":{"_index":"{索引名称}","_type":"{类型}","_id":"{id_1}"}} {"delete":{"_index":"{索引名称}","_type":"{类型}","_id":"{id_2}"}} {"delete":{"_index":"{索引名称}","_type":"{类型}","_id":"{id_3}"}}
5. 分页操作
ES搜索默认最多返回10条数据,需要分页返回
请求形式 POST 参数: ?size=n1&from=n2 size: 每页显示的结果数量 from: 跳过多少结果数 URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search?size=3&from=0 /* 每页显示四条数据,显示第二页 */ URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search?size=4&from=4
6. 映射操作
如果没有指定字段类型,ES会默认给字段赋上相应类型
ES支持的基本数据类型:
- 字符串:
- text:存储数据时,会自动分词,并生成索引
- keyword:存储数据时,不会分词,直接整个词去建索引
- 整数 : byte, short, integer, long
- 浮点数 : float、double
- 布尔型 : boolean
- 日期 : date
/* 创建索引的映射信息 */ 请求形式 PUT URL: http://{ELK服务地址}:9200/{索引名称} JSON { "settings": { "index": { "number_of_shards": 2, "number_of_replicas": 0 } }, "mappings": { "properties": { "name": { "type": "text" }, "age": { "type": "integer" }, "email": { "type": "keyword" }, "hobby": { "type": "text" } } } } /* 查询索引的映射信息 */ 请求形式 GET 参数: _mapping URL: http://{ELK服务地址}:9200/{索引名称}/_mapping
7. 结构化查询
/* term查询 - 用于精确匹配某些值 */ 请求形式 POST URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 例如:查询年龄为26的数据信息 */ JSON { "query": { "term": { "age": 26 } } } /* terms查询 - 和term类似,但terms允许指定多个匹配条件 */ /* 某个字段指定了多个值,那么文档需要一起去匹配 */ 请求形式 POST URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 例如:查询年龄为26和30的用户数据信息 */ JSON { "query": { "term": { "age": [26, 30] } } } /* range查询 - 允许按照指定的范围查找数据 */ 请求形式 POST 范围操作符: gt:大于 gte:大于等于 lt:小于 lte:小于等于 URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 例如:查询年龄大于等于26小于30的用户数据信息 */ JSON { "query": { "term": { "age": { "gte": 26, "lt": 30 } } } } /* exists查询 - 用于查找文档中是否包含指定字段/没有某个字段,类似SQL的is null */ 请求形式 POST URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 例如:查询包含title字段的数据 */ JSON { "query": { "exists": { "field":"title" } } } /* match查询 - 全文本查询(模糊)以及精确查询都可以用 */ 请求形式 POST URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 例如:查询名字中带“云”字的数据信息 */ JSON { "query": { "match": { "name": "云" } } } /* bool查询 - 合并多个条件的查询结果的布尔逻辑 */ 请求形式 POST 操作符: must:多个查询条件完全匹配,AND must_not:多个查询条件的相反匹配,NOT should:至少有一个查询条件匹配,OR URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 例如:查询用户性别为男的且年龄不大于30岁的数据 */ JSON { "query": { "bool": { "must": { "match": { "sex": "男" } }, "must_not": { "range": { "age": { "gt": 30 } } } } } } /* filter查询 - 其他查询都需要计算查询结果的匹配程度,即元数据_source */ /* 过滤查询不考虑_source,且可以缓存查询结果,提升速度 */ 请求形式 POST URL: http://{ELK服务地址}:9200/{索引名称}/{类型}/_search /* 例如:查询年龄为26岁的用户数据 */ JSON { "query": { "bool": { "filter": { "term": { "age": 26 } } } } }
8. IK Analyse
请求形式 POST URL: http://{ELK服务地址}:9200/_analyze /* 英文分词 */ JSON { "analyzer": "standard", // 默认英文分词器 "text": "hello world" // 分词文本 } /* 中文分词 */ JSON { "analyzer": "ik_max_word", //ik中文分词器名称为ik_max_word "text": "你好,中国" // 分词文本 }
9. 全文检索
请求形式 POST URL: http://{ELK服务地址}:9200/{索引名称}/_search /* 单词查询 */ JSON { // hobby这个field匹配 篮球 这个单词 "query": { "match": { "hobby": "篮球" } }, // 结果高亮 "highlight": { "fields": { "hobby": {} } } } /* 多词查询 - 匹配多个单词 */ JSON { // hobby这个field匹配 篮球 足球 这两个单词 "query": { "match": { "hobby": "篮球 足球" } }, // 结果高亮 "highlight": { "fields": { "hobby": {} } } } /* 多词查询 - 同时匹配多个单词 */ JSON { // hobby这个field同时匹配 篮球和足球 这两个单词 "query": { "match": { "hobby": { "query": "篮球 足球", "operator":"and" // AND OR两种情况 } } }, // 结果高亮 "highlight": { "fields": { "hobby": {} } } } /* 多词查询 - 设置匹配度40%进行查询 */ JSON { // hobby这个field同时匹配 篮球和足球 这两个单词 "query": { "match": { "hobby": { "query": "篮球 足球", "minimum_should_match":"40%" // 设置匹配度,_source分数越高匹配度越大 } } }, // 结果高亮 "highlight": { "fields": { "hobby": {} } } }
- 字符串:
- 相关度分数:匹配程度,分数越高越相关
- _index
- 重启kibana
- kibana的配置文件出了问题,所以要修改配置文件,找到kibana.yml,进入修改
- 进入docker容器
- cd进入_site/目录,编辑vendor.js
猜你喜欢
网友评论
- 搜索
- 最新文章
- 热门文章