概述
Elasticsearch的强大之处就是可以模糊查询。SQL也可以模糊查询,但是SQL的数据量一旦特别大,耗时就会非常长。Elasticsearch可以快速地储存、搜索和分析海量数据。维基百科、Stack Overflow、Github 都采用它。
Elastic 的底层是开源库 Lucene。Lucene只是一个库。 想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,糟糕的是, Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的,你没法直接用 Lucene,必须自己写代码去调用它的接口。ElasticSearch是基于Lucene 做了一下封装和增强,提供了 REST API 的操作接口,开箱即用。es通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
官网
https://www.elastic.co/cn/downloads/elasticsearch
小故事
多年前,一个叫做Shay Banon的刚结婚不久的失业开发者,由于妻子要去伦敦学习厨师,他便跟着也去了。在他找工作的过程中,为了给妻子构建一个食谱的搜索引擎,他开始构建一个早期版本的Lucene。
直接基于Lucene工作会比较困难,所以Shay开始抽象Lucene代码以便lava程序员可以在应用中添加搜索功能。他发布了他的第一个开源项目,叫做“Compass”。
后来Shay找到一份工作,这份工作处在高性能和内存数据网格的分布式环境中,因此高性能的、实时的、分布式的搜索引擎也是理所当然需要的。然后他决定重写Compass库使其成为一个独立的服务叫做Elasticsearch。
第一个公开版本出现在2010年2月,在那之后Elasticsearch已经成为Github上最受欢迎的项目之一,代码贡献者超过300人。一家主营Elasticsearch的公司就此成立,他们一边提供商业支持一边开发新功能,不过Elasticsearch将永远开源且对所有人可用。
Shay的妻子依旧等待着她的食谱搜索……
Elasticsearch的数据结构
- 正向索引:如同目录
- 倒排索引:也可以称作反向索引或者Lucene索引底层,(正向索引如同目录)一般是根据某个不完整的词再查找对应记录,叫做倒排索引。简单说就是按
文章关键字,对应的文档(0个或多个)
形式建立索引,根据关键字就可直接查询对应的文档(含关键字的),无需查询每一个文档,如下图
Elastic 默认端口:9200端口
基本概念
可以把es看做一个DB,概念之间有互通,可以近似理解
elasticsearch(集群)中可以包含多个索引(数据库) ,每个索引中可以包含多个类型(表) ,每个类型下又包含多个文档(行) ,每个文档中又包含多个字段(列)。
1. DSL:相当于数据库的SQL语句
2. 文档Document(相当于数据库的一行记录):
索引和搜索数据的最小单位是文档。
Index 里面单条的记录称为 Document(文档),许多条 Document 构成了一个 Index。
Document 使用 JSON 格式表示,下面是一个例子。
{
"user": "张三",
"title": "工程师",
"desc": "数据库管理"
}
同一个 Index 里面的 Document,不要求有相同的结构(scheme),但是最好保持相同,这样有利于提高搜索效率。
3. 类型Type (7.x 版移除 Type)
Document 可以分组,比如weather
这个 Index 里面,可以按城市
分组(北京和上海)
,也可以按气候
分组(晴天和雨天)
。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document。
不同的 Type 应该有相似的结构(schema),举例来说,id字段不能在这个组是字符串,在另一个组是数值。这是与关系型数据库的表的一个区别。性质完全不同的数据(比如products和logs)应该存成两个 Index,而不是一个 Index 里面的两个 Type(虽然可以做到)。
根据规划,Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type。
4. 索引Index(相当于数据库)
index就是一个非常大的文档集合
Elastic 会索引所有字段,经过处理后写入一个反向索引,也可以称为倒排索引(Inverted Index)。查找数据的时候,直接查找该索引。
所以,Elastic 数据管理的顶层单位就叫做 Index(索引)。它是单个数据库的同义词。每个 Index (即数据库)的名字必须是小写。
Elasticsearch最外层的是Index(相当于数据库 表的概念);一个Index的数据我们可以分发到不同的Node上进行存储,这个操作就叫做分片,默认分片为5
。分片的原因:如果一个Index的数据量太大,只有一个分片,那只会在一个节点上存储,随着数据量的增长,一个节点未必能把一个Index存储下来。
一个集群至少有一个节点,而一个节点就是一个elasricsearch进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5个分片(primary shard ,又称主分片)构成的,每一个主分片会有一个副本(replica shard,又称复制分片)
多个分片,在写入或查询的时候就可以并行操作(从各个节点中读写数据,提高吞吐量),分片会有主分片和副本分片之分(为了实现高可用)数据写入的时候是写到主分片,副本分片会复制主分片的数据,读取的时候主分片和副本分片都可以读。Index需要分为多少个分片和副本分片都是可以通过配置设置的
下面的命令可以查看当前节点的所有 Index。
GET _search
{
"query":{
"match_all":{}
}
}
5. Node 与 Cluster
Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例。
单个 Elastic 实例称为一个节点(node)。一组节点构成一个集群(cluster)。
Master Node
它主要负责维护索引元数据、负责切换主分片和副本分片身份等工作(可以理解成hdfs的activeNode),如果主节点挂了,会选举出一个新的主节点。
中文分词设置
首先,安装中文分词插件。如果要使用中文,建议使用IK分词器,也可以考虑其他插件(比如 smartcn)。IK分词器提供了两个分词算法:ik_smart(最少切分)
和ik_max_word(最细粒度划分:穷尽词库所有可能)
。
分词:把一段中文或者其他文字划分为一个个的关键字,搜索时会把自己的信息进行分词。
官网:https://github.com/medcl/elasticsearch-analysis-ik/releases
$ ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.5.1/elasticsearch-analysis-ik-5.5.1.zip
上面代码安装的是5.5.1版的插件,与 Elastic 5.5.1 配合使用。
接着,放入Elastic的plugins目录中,重新启动 Elastic,就会自动加载这个新安装的插件。
数据操作(增删改查)
基本Rest命令说明:
method | url地址 | 描述 |
---|---|---|
PUT(创建,修改) | localhost:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST(创建) | localhost:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST(修改) | localhost:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE(删除) | localhost:9200/索引名称/类型名称/文档id | 删除文档 |
GET(查询) | localhost:9200/索引名称/类型名称/文档id | 查询文档通过文档ID |
POST(查询) | localhost:9200/索引名称/类型名称/文档id/_search | 查询所有数据 |
字段数据类型
- 字符串类型
- text、keyword
- text:支持分词,全文检索,支持模糊、精确查询,不支持聚合,排序操作;text类型的最大支持的字符长度无限制,适合大字段存储;
- keyword:不进行分词,直接索引、支持模糊、支持精确匹配,支持聚合、排序操作。keyword类型的最大支持的长度为——32766个UTF-8类型的字符,可以通过设置ignore_above指定自持字符长度,超过给定长度后的数据将不被索引,无法通过term精确匹配检索返回结果。
- text、keyword
- 数值型
long、Integer、short、byte、double、float、half float、scaled float - 日期类型
date - 布尔类型
boolean - 二进制类型
binary
通过get _cat/ 可以获取ElasticSearch的当前的很多信息
通过 GET 请求发送 cat 命名可以列出所有可用的 API:
=^.^=(顶上有一只猫)
/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/master
/_cat/nodes
/_cat/indices
/_cat/indices/{index}
/_cat/segments
/_cat/segments/{index}
/_cat/count
/_cat/count/{index}
/_cat/recovery
/_cat/recovery/{index}
/_cat/health
/_cat/pending_tasks
/_cat/aliases
/_cat/aliases/{alias}
/_cat/thread_pool
/_cat/plugins
/_cat/fielddata
/_cat/fielddata/{fields}
1. 增
创建一个索引
PUT /test1/type1/1
{
"name" : "hzy",
"age" : 25
}
指定字段的类型
PUT /test2
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age":{
"type": "long"
},
"birthday":{
"type": "date"
}
}
}
}
2. 删
GET /test1
DELETE /test1
3. 改
有两种方案
旧方案,使用put进行修改(会覆盖原来的值,相当于删除旧数据,插入新数据):
PUT /test3/_doc/1
{
"name" : "es真的很有意思",
"age" : 25,
"birth" : "1996-02-15"
}
GET /test3/_doc/1
//如果漏掉某个字段没有写,原先的其他字段值会消失
PUT /test3/_doc/1
{
"name" : "es真没意思,再也不学了"
}
GET /test3/_doc/1
新方案,使用post的update(需要注意doc字段,不会丢失字段):
POST /test3/_doc/1/_update
{
"doc":{
"name" : "es的新修改方式"
}
}
GET /test3/_doc/1
如果执行后可以看到,记录的 Id 没变,但是版本(version)从1变成2,操作类型(result)从created变成updated,created字段变成false,因为这次不是新建记录。
4. 查
获取建立的规则
GET test2
获取默认信息
PUT /test3/_doc/1
{
"name": "hzy",
"age": 25,
"birth": "1996-02-15"
}
GET test3
花样查询
简单条件的查询:
GET /test3/_doc/_search?q=name:hzy
匹配查询:
- match:匹配(会使用分词器解析(先分析文档,然后进行查询))
- _source:过滤字段
- sort:排序
- form、size 分页
GET /blog/user/_search
{
"query":{
//匹配
"match":{
"name":"hzy"
}
},
//过滤字段
"_source": ["name","desc"],
"sort": [
{
//按照年龄升序排列
"age": {
"order": "asc"
}
}
],
//从索引0开始,也就是从第一个开始
"from": 0,
//限制展示数量
"size": 1
}
多条件查询
- must 相当于 and
- should 相当于 or
- must_not 相当于 not (… and …)
- filter 过滤
GET /blog/user/_search
{
"query":{
"bool": {
"must": [
{
"match":{
"age":3
}
},
{
"match": {
"name": "hzy"
}
}
],
"filter": {
"range": {
"age": {
"gte": 1,
"lte": 3
}
}
}
}
}
}
待续