ElasticSearch学习

ElasticSearch

Es概念介绍

ElasticSearch:简称为ES,基于Lucene全文检索引擎服务,支持分布式集群(数据横向扩展、分布式计算)
应用场景:全文检索或者搜索服务;NOSQL数据库(ES中的数据单元为JSON);ELK数据分析平台

NRT (near real time) 接近实时 ES中的一条数据写入后大概会有1s的延迟才能被检索到
9300端口:Es节点之间通讯使用 9200:Es节点和外部通讯使用

名词介绍

名词说明额外补充
索引(index)类似于数据库中的database
类型(type)相当于sql中的tableEs6.0以后删除了类型的概念,6.0还可以设置类型,但只能设置一个
文档(Document)相当于sql中的一行记录
分片(Shard)每个索引都有1到多个分片, 每个分片都是一个luncene索引片的好处: 分摊索引的搜索压力, 分片还支持水平的拓展和拆分以及分布式的操作, 可以提高搜索和其他处理的效率
备份/复制(replicas)拷贝一个分片就完成了分片的备份备份的好处: 当主分片失败或者挂掉, 备份就可以代替分片进行操作, 进而提高了es的可用性, 备份的分片还可以进行搜索操作, 以分摊搜索的压力.
映射(Mapping)类似于Table的Schema(模式)例如:create table person_info(name varchar(20),age tinyint)创建一张表,person后的括号是定义表中的字段,即为Schema

在这里插入图片描述

analyzer(分析器)介绍

analyzer(分析器)是一个包,这个包由三部分组成,分别是:character filters (字符过滤器)、tokenizer(分词器)、token filters(token过滤器)。
一个analyzer可以有0个或多个character filters
一个analyzer有且只能有一个tokenizer
一个analyzer可以有0个或多个token filters
character filter 是做字符转换的,它接收的是文本字符流,输出也是字符流
tokenizer 是做分词的,它接收字符流,输出token流(文本拆分后变成一个一个单词,这些单词叫token)
token filter 是做token过滤的,它接收token流,输出也是token流
由此可见,整个analyzer要做的事情就是将文本拆分成单个单词,文本 ----> 字符 ----> token
分析器的任务是分析(Analyze)文本数据,分析是分词,规范化文本的意思

ES在创建索引时, 默认创建5个分片(shard), 每个分片有一份备份/复制分片(replica shard), 可以修改, 分片的数量只能在创建索引的时候指定, 索引创建后就不能修改分片的数量了, 而备份是可以动态修改的

反向索引又叫倒排索引,是根据文章内容中的关键字建立索引
Keyword 类型是不会分词的,直接根据字符串内容建立反向索引,Text 类型在存入 Elasticsearch 的时候,会先分词(指定分词器会按指定分词器分词,未指定按默认分词器分词)),然后根据分词后的内容建立反向索引

java REST api是通过http访问,走9200端口(java api是9300端口)。
虽然es带有java api,但是会引起版本兼容性的问题,以及微弱到可以忽略的性能提升,并且java api在未来的es版本会放弃,官方推荐使用java REST api

每个elasticsaerch分片都是一个Lucene 索引。在单个索引中你最多可以存储2147483519 (= Integer.MAX_VALUE - 128) 个文档。你可以使用 _cat/shards api去监控分片的的大小。

Es配置文件

vim elasticsearch.yml

#集群名字,es启动后会将具有相同集群名字的节点放到一个集群下。
cluster.name:  elasticsearch
#节点名字
node.name: "es-node1"
#指定集群中的节点中有几个有master资格的节点。
#对于大集群可以写3个以上。
discovery.zen.minimum_master_nodes: 2
#设置集群中自动发现其它节点时ping连接超时时间,默认是3s,
#为避免因为网络差而导致启动报错,设成了40s。
discovery.zen.ping.timeout: 40s
#设置是否打开多播发现节点,默认是true
discovery.zen.ping.multicast.enabled: false
#ip地址
network.host: 192.168.137.100
#指明集群中其它可能为master的节点ip,以防es启动后发现不了集群中的其他节点。
discovery.zen.ping.unicast.hosts:["节点1的ip","节点2的ip","节点3的ip"]

一般测试时,只需要改一下cluster.name、node.name、network.host即可,使用默认也可以

Es启动:

启动:# bin/elasticsearch
发生以下错误:Caused by: java.lang.RuntimeException: can not run elasticsearch as root(不能用root用户启动)    原因:root用户权限过大
解决方案: useradd es (添加一个es用户)
		 passwd es (设置用户es密码)
		 chown -R es:es * (给es用户权限)
su -es (切换用户)
切换到上面新添加的es用户再次执行启动命令:此时可能会出现3个错误
ERROR: [3] bootstrap checks failed
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at
least [65536]
	解决(切换到root用户):
	vim /etc/security/limits.conf
	# 添加以下内容(*也是,代表所有用户):增大内存和硬盘
    * soft nofile 65536
    * hard nofile 131072
    * soft nproc 2048
    * hard nproc 4096
[2]:max number of threads [3802] for user [es] is too low, increase to at least [4096]
	解决:
	vim /etc/security/limits.d/90-nproc.conf(用户最大线程数)
	修改以下内容
	*	soft	nproc	4096(原先是1024)
[3]:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least
[262144]	
	解决:
	vim /etc/sysctl.conf(配置最大线程数)
	# 添加以下内容
	vm.max_map_count=655360

再次切换到es用户执行启动命令成功启动

Kibana工具

当es启动后,我们在命令行直接敲es命令是比较麻烦的,因此此时用到kibana插件,kibana是es的一个可视化视图工具,当然es也有其他的插件,比如elasticsearch-headElasticHD等等

kibana的安装

kibana下载地址:https://www.elastic.co/cn/downloads/kibana,注意:下载的版本要和es使用的版本要对应
kibana的配置文件

vim  kibana.yml
#对外服务监听端口
server.port: 5601
#绑定可以访问5601端口服务的IP地址,0.0.0.0表示任何地址在没有防火墙限制的情况下都可以访问,生产环境别这样设置,不安全。
server.host: "0.0.0.0"
#默认值为主机名称,表示kibana实例绑定的主机,可以是IP地址或者主机名称.
server.name: "192.168.1.11"
#用来处理ES请求的服务URL
elasticsearch.hosts: ["http://192.168.1.11:9200","http://192.168.1.12:9200"]
#用来控制证书的认证,可选的值为full,none,certificate。此处由于没有证书,所以设置为null,否则启动会提示错误.
elasticsearch.ssl.verificationMode: none
#kibana搜索数据请求超时时间
elasticsearch.requestTimeout: 90000

更多配置信息查看:https://www.elastic.co/guide/en/kibana/5.6/settings.html

启动命令:kibana文件夹bin/kibana

Es集群相关操作

查看集群健康信息	GET /_cat/health?
	查看集群中节点信息	GET /_cat/nodes?v
	查看集群中的索引信息	GET /_cat/indices?v
	可以看到我们集群叫“elasticsearch”,运行状态是green。每当我们查询集群健康情况时,接口可能会返回green,yellow或red状态。green意味着一切良好(集群所有的功能都正常)。
yellow意味着所有的数据都是可用的,但是一些复制分片可能没有正确分发(集群的所有功能还是正常的)。red意味着因为某些原因导致有些数据不能使用。
注意,即使集群状态是red,它仍然可以运行一部分的功能。(例如,它依然可以从一些可用的分片处理搜索请求)但你应该尽快去修复它,因为这样会使搜索结果丢失一些数据

索引相关操作

简单操作:	创建:	put/索引名		删除:delete/索引名

put、get、post、delete操作
	添加数据
	put 索引名/类型名/文档(id)	{json数据}
		不指定类型(id),会随机生成id值,但只能用post post 索引名/类型名 {json数据}
	获取数据	get 索引名/类型名/文档(id)
	测试文档是否存在	
        HEAD 索引名/类型名/文档(id)		
        200 - OK	200:该文档存在		404 - Not Found		404:该文档不存在
	批量获取	主要是Get (索引名/类型名)_mget	{json数据}	具体分类看保存的图片
批处理操作
	POST /索引名/类型/_bulk # 批量插入多个document
    {"index":{}}
    {"name":"ww","title":"王五","age":18,"created":"2018-12-27"}
    {"index":{}}
    {"name":"zl","title":"赵六","age":25,"created":"2018-12-27"}
    POST /索引名/类型名/_bulk # 批量操作(包含修改和删除)
    {"update":{"_id":"KrOP6WcBVEuCC3JS8V9K"}} # 修改
    {"doc":{"title":"王小五"}}
    {"delete":{"_id":"K7OP6WcBVEuCC3JS8V9K"}} # 删除    
es更新文档的原理为:先找到这个文档,删除旧的文档内容执行更新,更新完后再索引最新的文档
	
过滤器	注意: 过滤查询运行时先执行过滤语句,后执行普通查询	
	过滤器的类型
	1. term 、 terms Filter
	term、terms的含义与查询时一致。term用于精确匹配、terms用于多词条匹配
	2. ranage filter	3. exists filter	4. ids filter
QueryFilter更详细的对比可参考:https://blog.csdn.net/laoyang360/article/details/80468757

Mapping Type1. 简单类型: text , keyword , date , long , double , boolean or ip
2. 其它类型: object , geo_point , geo_shape 等

查看类型mapping			GET /索引名/_mapping/类型名    GET 索引名/_mapping?pretty
查看某个字段的分词结果
GET your_index/your_type/your_id/_termvectors?fields=your_fieldsName

IK分词器
elasticSearch默认的分词器对中文不是很友好,会将中文单个字的建立索引(标准分词器对于英文单词分词,对于中文单字分词),因此可以使用ik分词器

ik分词器下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases
同样,版本尽量和Es相对应。
下载完以后在Es的plugins文件夹中创建一个名为IK的文件夹,将下载的ik分词器解压到该文件夹下,
重新启动Es,出现plugin [analysis-ik]说明ik分词器被加载。

Ik分词器的两种方式:
智能模式和细粒度模式(智能:对应es的IK插件的ik_smart,细粒度:对应es的IK插件的ik_max_word)
细粒度分词,包含每一种切分可能(更全);而智能模式,只包含各种切分路径中最可能的一种。

Es中高级检索

6.0以后删除类型了,下面的查询条件可以把索引类型去掉,因为这是6.0之前的语句,可以根据版本决定是否去掉

1.查询所有(match_all)

GET /索引名/索引类型/_search
{
 	"query": { "match_all": {} }
}

2.查询结果中返回指定条数(size)

size 关键字: 指定查询结果中返回指定条数。 默认返回值10条

GET /索引名/索引类型/_search
{
 	"query": { "match_all": {} },
	"size": 1
}

3. 分页查询(from、scroll)

浅分页:from+size

from/size的原理:因为es是基于分片的,假设有5个分片,from=100,size=10。则会根据排序规则从5个分片中各取回100条数据数据,然后汇总成500条数据后选择最后面的10条数据。

GET /索引名/索引类型/_search
{
      "query": {"match_all": {}},
      "sort": [
        {
          "age": {
            "order": "desc"
          }
        }
      ],
      "size": 2, 
      "from": 1
}

优点:from+size在数据量不大的情况下,效率比较高
缺点:在数据量非常大的情况下,from+size分页会把全部记录加载到内存中,这样做不但运行速递特别慢,而且容易让es出现内存不足而挂掉

为了解决上面的问题,elasticsearch提出了一个scroll滚动的方式。
scroll 类似于sql中的cursor(游标),使用scroll,每次只能获取一页的内容,然后会返回一个scroll_id。根据返回的这个scroll_id可以不断地获取下一页的内容,所以scroll并不适用于有跳页的情景。

深分页:scroll

scroll分为初始化遍历两步
初始化:

GET /索引名/索引类型/_search?scroll=3m
{
  "query": {"match_all": {}},
   "size": 3,
   "from": 0
}
  1. scroll=3m代表当前查询的数据缓存3分钟
  2. size:3 代表当前查询3条数据
  3. from:起始位置,使用scroll必须要将from设置为0,可以不写使用默认值。

遍历: 初始化时会返回一个scoll_id,用于下面的遍历查询

GET _search/scroll
{
  "scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAJZ9Fnk1d......",
  "scroll": "5m"
}

注意:请求的接口不再使用索引名了,而是 _search/scroll,其中GET和POST方法都可以使用。

scroll删除
根据官方文档的说法,scroll的搜索上下文会在scroll的保留时间截止后自动清除,但是我们知道scroll是非常消耗资源的,所以一个建议就是当不需要了scroll数据的时候,尽可能快的把scroll_id显式删除掉。

清除指定的scroll_id:
DELETE _search/scroll/DnF1ZXJ5VGhlbkZldGNo.....

清除所有的scroll:
DELETE _search/scroll/_all

深分页:search_after
scroll 的方式,官方的建议不用于实时的请求(一般用于数据导出),因为每一个 scroll_id 不仅会占用大量的资源,而且会生成历史快照,对于数据的变更不会反映到快照上。

search_after 分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到游标上。但是需要注意,因为每一页的数据依赖于上一页最后一条数据,所以无法跳页请求。

为了找到每一页最后一条数据,每个文档必须有一个全局唯一值,官方推荐使用 _uid 作为全局唯一值,其实使用业务层的 id 也可以。

GET 索引名/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "age": 28
          }
        }
      ]
    }
  },
  "size": 20,
  "from": 0,
  "sort": [
    {
      "timestamp": {
        "order": "desc"
      },
      "_id": {
        "order": "desc"
      }
    }
  ]
}
  1. 使用search_after必须要设置from=0。
  2. 这里我使用timestamp和_id作为唯一值排序。
  3. 我们在返回的最后一条数据里拿到sort属性的值传入到search_after。

使用sort返回的值搜索下一页:

GET 索引名/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "age": 28
          }
        }
      ]
    }
  },
  "size": 10,
  "from": 0,
  "search_after": [
    1541495312521,
    "d0xH6GYBBtbwbQSP0j1A"
  ],
  "sort": [
    {
      "timestamp": {
        "order": "desc"
      },
      "_id": {
        "order": "desc"
      }
    }
  ]
}

4.关键词查询(term)

term 关键字: 用来使用关键词查询

GET /索引名/索引类型/_search
{
  "query": {
    "term": {
      "address": {
        "value": "北京"
      }
    }
  }
}

在ES使用标准分词器(StandardAnalyzer)时,Mapping Type 中 keyword , date ,integer, long , double , boolean or ip 这些类型不分词,只有text类型分词。

5.范围查询(range)

range 关键字: 用来指定查询指定范围内的文档
gt:> ;lt: <;gte: >=;lte: <=

GET /索引名/索引类型/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 8,
        "lte": 30
      }
    }
  }
}

6. 前缀查询(prefix)

prefix 关键字: 用来检索含有指定前缀的关键词的相关文档

GET /索引名/索引类型/_search
{
  "query": {
    "prefix": {
      "content": {
        "value": "redis"
      }
    }
  }
}

7.通配符查询(wildcard)

wildcard 关键字: 通配符查询 ? 用来匹配一个任意字符 * 用来匹配多个任意字符

GET /索引名/索引类型/_search
{
  "query": {
    "wildcard": {
      "content": {
        "value": "re*"
      }
    }
  }
}

8.多id查询(ids)

ids 关键字 : 值为数组类型,用来根据一组id获取多个对应的文档

GET  /索引名/索引类型/_search
{
  "query": {
    "ids": {
      "values": ["lg5HwWkBxH7z6xax7W3_","lQ5HwWkBxH7z6xax7W3_"]
    }
  }
}

9. 模糊查询(fuzzy)

fuzzy 关键字: 用来模糊查询含有指定关键字的文档

GET /索引名/索引类型/_search
{
  "query": {
    "fuzzy": {
      "content":"spring"
    }
  }
}

10. 布尔查询(bool)

bool 关键字: 用来组合多个条件实现复杂查询

must: 相当于&& 同时成立

should: 相当于|| 成立一个就行

must_not: 相当于! 不能满足任何一个

GET /索引名/索引类型/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "age": {
              "gte": 0,
              "lte": 30
            }
          }
        }
      ],
      "must_not": [
        {"wildcard": {
          "content": {
            "value": "redi?"
          }
        }}
      ]
    }
  },
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ]
}

11. 高亮查询(highlight)

highlight 关键字: 可以让符合条件的文档中的关键词高亮

GET /索引名/索引类型/_search
{
  "query": {
    "term": {
      "content": {
        "value": "redis"
      }
    }
  },
  "highlight": {
    "fields": {
      "*": {}
    }
  }
}

自定义高亮html标签: 可以在highlight中使用pre_tagspost_tags

GET /索引名/索引类型/_search
{
  "query":{
    "term":{
      "content":"框架"
    }
  },
  "highlight": {
    "pre_tags": ["<span style='color:red'>"],
    "post_tags": ["</span>"],
    "fields": {
      "*":{}
    }
  }
}

多字段高亮: 使用require_field_match开启多个字段高亮

GET /索引名/索引类型/_search
{
  "query":{
    "term":{
      "content":"框架"
    }
  },
  "highlight": {
    "pre_tags": ["<span style='color:red'>"],
    "post_tags": ["</span>"],
    "require_field_match":false,
    "fields": {
      "*":{}
    }
  }
}

12. 多字段查询(multi_match)

GET /索引名/索引类型/_search
{
  "query": {
    "multi_match": {
      "query": "中国",
      "fields": ["name","content"] #这里写要检索的指定字段
    }
  }
}

13. 多字段分词查询(query_String)

GET /索引名/索引类型/_search
{
  "query": {
    "query_string": {
      "query": "中国声音",
      "analyzer": "ik_max_word", 
      "fields": ["name","content"]
    }
  }
}

14. 过滤查询 (filter query)

其实准确来说,ES中的查询操作分为2种: 查询(query)过滤(filter)
查询即是之前提到的query查询,它 (查询)默认会计算每个返回文档的得分,然后根据得分排序。而过滤(filter)只会筛选出符合的文档,并不计算得分,且它可以缓存文档 。所以,单从性能考虑,过滤比查询更快。
换句话说,过滤适合在大范围筛选数据,而查询则适合精确匹配数据。一般应用时, 应先使用过滤操作过滤数据, 然后使用查询匹配数据。

过滤语法

GET /索引名/索引类型/_search
{
  "query": {
    "bool": {
      "must": [
        {"match_all": {}}
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 10
          }
        }
      }
    }
  }
}
  1. 在执行filter和query时,先执行filter在执行query
  2. Elasticsearch会自动缓存经常使用的过滤器,以加快性能。

常见的过滤器类型
term 、 terms Filter

GET /索引名/索引类型/_search   # 使用term过滤
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "小黑"
          }
        }}
      ],
      "filter": {
        "term": {
          "content":"框架"
        }
      }
    }
  }
}
GET /索引名/索引类型/_search  #使用terms过滤
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "中国"
          }
        }}
      ],
      "filter": {
        "terms": {
          "content":[
              "科技",
              "声音"
            ]
        }
      }
    }
  }
}

ranage filter

GET /索引名/索引类型/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "中国"
          }
        }}
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 7,
            "lte": 20
          }
        }
      }
    }
  }
}

exists filter:过滤存在指定字段,获取字段不为空的索引记录使用

GET /索引名/索引类型/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "中国"
          }
        }}
      ],
      "filter": {
        "exists": {
          "field":"aaa"
        }
      }
    }
  }
}

ids filter:过滤含有指定字段的索引记录

GET /索引名/索引类型/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "中国"
          }
        }}
      ],
      "filter": {
        "ids": {
          "values": ["1","2","3"]
        }
      }
    }
  }
}

向es的mapping中添加新字段

PUT /索引名/_mapping/
{
  "properties": {
       "新增字段": {
           "type":     "text",
           "fields":{
             "keyword":{
               "type":"keyword",
               "ignore_above" : 256
             }
           }
       }
   }
}

--给新字段赋值(原先的数据)
POST 索引名/_update_by_query
{
  "script": {
    "lang": "painless",
    "inline": "if (ctx._source.新增字段== null) {ctx._source.新增字段 = '值'}"
  }
}

sql语句转es语句

http://www.ischoolbar.com/EsParser/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值