赞
踩
引言:
本文主要分享了有关Elasticsearch(简称ES)的知识,包括:ES的简介、基本概念、倒序索引、ES的安装以及使用、Kibana可视化工具的安装与使用、分词的使用、使用可视化工具Kibana实现索引和文档的增删查改、以及一些高级的ES查询,如:批量获取文档信息、使用Bulk API实现批量操作、采用乐观锁机制实现并发控制、Mapping、通用查询(分词查找、短语查询、返回指定字段、高亮查询、范围查询 )、Bool过滤查询、范围查询、聚合查询等等;
Elasticsearch 是一个开源的搜索引擎, 建立在全文搜索引擎库 Apache Lucene 基础上;内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单,通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTFUL API;
Elasticsearch 不仅仅只是一个全文搜索引擎是一个分布式的实时文档存储,每个字段可以被索引与搜索可以作数据库用;还是一个分布式实时分析搜索引擎,能胜任上百个服务节点的扩展,并支持PB级别(大数据级别)的结构化(定死的,进去多少出来多少,多余的全部抛弃)或者非结构化数据(只需要直到其属性即可);
- Elasticsearch :分布式搜索引擎
- Logstash:日志的采集与解析工具
- Kibana:可视化分析平台
- Beats:数据采集工具家族(替换Logstash)
- X-Pack:功能包
Near Realtime(NRT) 近实时:数据提交索引后,立马就可以搜索到。
Cluster 集群:一个集群由一个唯一的名字标识,默认为“elasticsearch”。集群名称非常重要,具有相同集群名的节点才会组成一个集群。集群名称可以在配置文件中指定。
Node 节点:存储集群的数据,参与集群的索引和搜索功能。像集群有名字,节点也有自己的名称,默认在启动时会以一个随机的UUID的前七个字符作为节点的名字,你可以为其指定任意的名字。通过集群名在网络中发现同伴组成集群。一个节点也可是集群。
Index 索引:一个索引是一个文档的集合(等同于solr中的集合)。每个索引有唯一的名字,通过这个名字来操作它。一个集群中可以有任意多个索引。Type 类型:指在一个索引中,可以索引不同类型的文档,如用户数据、博客数据。从6.0.0 版本起已废弃,一个索引中只存放一类数据。
Document 文档:被索引的一条数据,索引的基本信息单元,以JSON格式来表示。
Shard 分片:在创建一个索引时可以指定分成多少个分片来存储。每个分片本身也是一个功能完善且独立的“索引”,可以被放置在集群的任意节点上。分片的好处:允许我们水平切分/扩展容量、可在多个分片上进行分布式的、并行的操作,提高系统的性能和吞吐量。
注意:分片数创建索引时指定,创建后不可改了。备份数可以随时改。
Replication 备份: 一个分片可以有多个备份(副本)。备份的好处:高可用。一个主分片挂了,副本分片就顶上去
扩展搜索的并发能力、吞吐量。搜索可以在所有的副本上并行运行。-高并发下副本也可搜索
平时的数据可以分为结构化数据和非结构化数据:
对于结构化数据,可以存储在DB中通过精确匹配找到。但是对于非结构化数据,一般查询时只能提供查询的局部信息或模糊信息,传统数据库无法根据这些信息进行查询,效率差;
倒排索引是相对于正排索引而言的,可以有效的解决该问题;
正排索引可以通过id查找到对应的文章,但是无法通过给的部分内容如elasticsearch,找出含有该关键字的文档。
倒排索引会先对文档进行分析将其拆分成单个Term, 并存储包含该Term的文档id,这样便可以实现通过内容查找对应文档,如包含elasticsearch的文档为文档1;
倒排索引的过程:
官网下载地址: https://www.elastic.co/downloads/elasticsearch
推荐到华为云镜像下载:https://mirrors.huaweicloud.com/
JDK版本: 1.8
解压安装包,进入bin目录中双击elasticsearch.bat等待启动完毕;
打开浏览器,输入 http://localhost:9200 出现以下画面,说明ES安装成功;
- 9300端口: ES节点之间通讯使用,9300是tcp通讯端口,集群间和TCPClient 都走它;
- 9200端口: ES节点和外部通讯使用,9200是http协议的RESTful接口;
Kibana是一个针对Elasticsearch的开源分析及可视化平台,使用Kibana可以查询、查看并与存储在ES索引的数据进行交互操作,同时也能执行高级的数据分析,并能以图表、表格和地图的形式查看数据 ;
下载安装包,需要和ES版本匹配,下载完毕后安装到相应的目录就行;
下载地址:https://www.elastic.co/downloads/kibana
在目录config/kibana.yml中配置 elasticsearch.hosts: 的值为ES的访问地址;
双击bin/kibana.bat
- 访问地址:http://localhost:5601
IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包;从3.0版本开始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化;
获取 ES-IKAnalyzer插件,需要和ES版本一致;
将ik的压缩包解压到 ES安装目录的plugins/目录下(新建文件夹analysis-ik),重启ES;
下载地址: https://github.com/medcl/elasticsearch-analysis-ik/releases
Ik分词器有ik_max_word和ik_smart两种模式:
- ik_max_word:会将文本做最细粒度的拆分;
- ik_smart:会做最粗粒度的拆分;
{
"text":"我爱学习,最爱学Java",
"analyzer":"ik_max_word"
}
{
"text":"我爱学习,最爱学Java",
"analyzer":"ik_smart"
}
首先在IKAnalyzer.cfg.xml里面定义自定义的字典,我这里是main.dic(自己随意命名);
<?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">main.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
PUT /kak
{
"settings": {
"index":{
"number_of_shards":5,
"number_of_replicas":3
}
}
}
#查看单个
GET /kak/_settings
#查看所有
GET /_all/_settings
PUT /kak/student/1
{
"name":"kaka",
"sex":"man",
"age":23,
"score":100
}
POST /kak/student/2
{
"name":"taotao",
"sex":"woman",
"age":23,
"score":100
}
GET /kak/student/1
GET /kak/student/_search
PUT方法:存在就修改,不存在就新增;
PUT /kak/student/1
{
"name":"kaka",
"sex":"man",
"age":23,
"score":150
}
#删除单个
DELETE /kak/student/2
#删除全部
DELETE /kak
创建索引、添加文档
PUT kak_01 PUT kak_01/student/1 { "name":"kaka", "age":23, "sex":"man" } PUT kak_01/student/2 { "name":"zhuangzhuang", "age":23, "sex":"woman" } PUT kak_02 PUT kak_02/student/1 { "name":"zhangsan", "age":23, "sex":"man" } PUT kak_02/student/2 { "name":"lisi", "age":23, "sex":"woman" }
GET /_mget
{
"docs":[
{
"_index": "kak_01",
"_type": "student",
"_id": 1
},
{
"_index": "kak_01",
"_type": "student",
"_id": 2
}
]
}
GET /_mget { "docs":[ { "_index":"kak_01", "_type":"student", "_id":1, "_source":["name","age"] }, { "_index":"kak_01", "_type":"student", "_id":2, "_source":["name","age","sex"] } ] }
GET /kak_01/student/_mget
{
"docs":[
{
"_id":1
},
{
"_id":2
}
]
}
语法格式:
{action:{metadata}}
{requstbody}
action:(行为)
- create:文档不存在时创建
- update:更新文档
- index:创建新文档或替换已有文档
- delete:删除一个文档
create 和index的区别:
- 如果数据存在,使用create操作失败,会提示文档已经存在;
- 如果数据存在,使用index则可以成功执行;
POST kak_01/student/_bulk
{"index":{"_id":3}}
{"name":"kak_03","age":23,"sex":"woman"}
{"index":{"_id":4}}
{"name":"kak_04","age":23,"sex":"woman"}
{"index":{"_id":5}}
{"name":"kak_05","age":23,"sex":"man"}
GET kak_01/student/_mget
{
"ids":[1,2,3]
}
POST kak_01/student/_bulk
{"delete":{"_index":"kak_01","_type":"student","_id":4}}
{"delete":{"_index":"kak_01","_type":"student","_id":5}}
操作的大小建议:
Bulk会把将要处理的数据载入内存中,所以数据量是有限制的,最佳的数据量不是一个确定的数值取决于硬件;
- 一般建议是1000-5000个文档,大小建议是5-15MB,默认不能超过100M,可以在ES的配置文件($ES_HOME下的config下的elasticsearch.yml)中设置;
ElasticSearch采用了乐观锁来保证数据的一致性,当用户对document进行操作时,并不需要对该document作加锁和解锁的操作,只需要指定要操作的版本;当版本号一致时,ElasticSearch会允许该操作顺利执行,当版本号存在冲突时,ElasticSearch会提示冲突并抛出异常(VersionConflictEngineException异常);
Elasticsearch在处理外部版本号时会与对内部版本号的处理有些不同。它不再是检查version是否与请求中指定的数值相同,而是检查当前的version是否比指定的数值小。如果请求成功,那么外部的版本号就会被存储到文档中的version中。为了保持version与外部版本控制的数据一致使用version_type=external ;
查看自动生成的映射情况
GET kak_01/_mapping
核心数据类型:
字符型:string
string类型包括,text 和 keyword
- text类型被用来索引长文本,在建立索引前会将这些文本进行分词,转化为词的组合,建立索引。允许es来检索这些词语。text类型不能用来排序和聚合。
- Keyword类型不需要进行分词,可以被用来检索过滤、排序和聚合。
- keyword 类型字段只能用本身来进行检索
数字型:long, integer, short, byte, double, float
日期型:date
布尔型:boolean
二进制型:binary
关键的属性:
“index”: true分词,false不分词,设置成false,字段将不会被索引;
“analyzer”:"ik"指定分词器,默认分词器为standard analyzer
PUT /lib
{
"settings":{
"number_of_shards" : 3,
"number_of_replicas" : 0
},
"mappings":{
"properties":{
"title":{"type":"text"},
"name":{"type":"text","analyzer":"standard"},
"publish_date":{"type":"date","index":false},
"price":{"type":"double"}
}
}
}
PUT /lib2 { "settings":{ "number_of_shards" : 3, "number_of_replicas" : 0 }, "mappings":{ "properties":{ "name": {"type":"text"}, "address": {"type":"text"}, "age": {"type":"integer"}, "interests": {"type":"text"}, "birthday": {"type":"date"} } } } PUT /lib2/_doc/1 { "name" : "kak", "address" : "sx", "age" : 32, "interests" : "java,music", "birthday": "1988-08-08" } PUT /lib2/_doc/2 { "name" : "taotao", "address" : "sz", "age" : 33, "interests" : "java,music,money", "birthday": "1983-08-08" } PUT /lib2/_doc/2 { "name" : "taotao", "address" : "sz", "age" : 33, "interests" : "java,music,money", "birthday": "1983-08-08" }
term查询
GET /lib2/_search/
{
"query": {
"term": {
"name": {
"value": "kak"
}
}
}
}
GET /lib2/_search/
{
"query": {
"terms": {
"interests": [
"java",
"music"
]
}
}
}
GET /lib2/_search
{
"from": 0,
"size": 2,
"query": {
"terms": {
"interests": [
"java",
"music"
]
}
}
}
GET /lib2/_search
{
"version": true,
"from":0,
"size": 2,
"query": {
"terms": {
"interests": [
"java",
"money"
]
}
}
}
match query知道分词器的存在,会对filed进行分词操作,然后再查询
GET /lib2/_search
{
"query": {
"match": {
"name": "kak helloworld"
}
}
}
GET /lib2/_search
{
"query": {
"multi_match": {
"query": "java",
"fields": ["interests","name"]
}
}
}
ElasticSearch引擎首先分析查询字符串,从分析后的文本中构建短语查询,这意味着必须匹配短语中的所有分词,并且保证各个分词的相对位置不变
GET /lib2/_search
{
"query": {
"match_phrase": {
"interests": "java,music"
}
}
}
GET /lib2/_search
{
"_source": ["address","name"],
"query": {
"match": {
"interests": "java"
}
}
}
GET /lib2/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
GET /lib2/_search
{
"query": {
"match_phrase_prefix": {
"name": {
"query": "kak"
}
}
}
}
GET /lib2/_search
{
"query": {
"range": {
"birthday": {
"from": "1988-08-08",
"to": "2020-08-08",
"include_lower": true,
"include_upper": false
}
}
}
}
允许使用通配符* 和 ?来进行查询:
- *代表0个或多个字符
- ?代表任意一个字符
GET /lib2/_search
{
"query": {
"wildcard": {
"name": "kak*"
}
}
}
GET /lib2/_search
{
"query": {
"match": {
"interests": "java"
}
},
"highlight": {
"fields": {
"interests": {}
}
}
}
- 可以实现组合过滤查询
- must:必须满足的条件(and)
- should:可以满足也可以不满足的条件(or)
- must_not:不需要满足的条件(not )
GET /lib2/_search
{
"post_filter": {
"bool": {
"should":[
{"term":{"age":32}},
{"term":{"interests":"java"}}
],
"must_not":{
"term":{"age":90}
}
}
}
}
GET /lib2/_search
{
"post_filter": {
"bool": {
"must":[
{"term":{"age":32}},
{"term":{"interests":"java"}}
]
}
}
}
- gt:>
- lt: <
- gte: >=
- lte: <=
GET /lib2/_search
{
"post_filter": {
"range": {
"age": {
"gte": 10,
"lte": 32
}
}
}
}
sum:求和
GET /lib2/_search
{
"size": 0,
"aggs": {
"agesum": {
"sum": {
"field": "age"
}
}
}
}
min:最小值
GET /lib2/_search
{
"size": 0,
"aggs": {
"agemin": {
"min": {
"field": "age"
}
}
}
}
- max:最大值
GET /lib2/_search
{
"size": 0,
"aggs": {
"agemax": {
"max": {
"field": "age"
}
}
}
}
- avg:平均值
GET /lib2/_search
{
"size": 0,
"aggs": {
"ageavg": {
"avg": {
"field": "age"
}
}
}
}
- cardinality:基数(互不相同的值的个数 )
GET /lib2/_search
{
"size": 0,
"aggs": {
"agecardinality": {
"cardinality": {
"field": "age"
}
}
}
}
- terms:分组
GET /lib2/_search
{
"size": 0,
"aggs": {
"ageterms": {
"terms": {
"field": "age"
}
}
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。