ElasticSearch 学习总结
ElasticSearch 官方网站:
安装
Elastic
需要 Java 8
环境。请参考 来安装 Java,可以解决环境配置的烦恼!
安装完 Java 8
后,在终端输入下面的命令来下载 Elastic
的压缩包( 版本号请自行修改 )。
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.1.zip$ unzip elasticsearch-5.5.1.zip$ cd elasticsearch-5.5.1/复制代码
启动
在一切准备工作(Java
安装完毕)做好后,进入 Elastic
文件的根目录下,输入下面的命令来启动 Elastic
。
$ ./bin/elasticsearch复制代码
启动完成后,打开浏览器,在地址栏输入 localhost:9200
,如果出现类似下面的信息,则说明启动成功。
{ "name" : "atntrTf", "cluster_name" : "elasticsearch", "cluster_uuid" : "tf9250XhQ6ee4h7YI11anA", "version" : { "number" : "5.5.1", "build_hash" : "19c13d0", "build_date" : "2017-07-18T20:44:24.823Z", "build_snapshot" : false, "lucene_version" : "6.6.0" }, "tagline" : "You Know, for Search"}复制代码
Ps. 推荐一个 API
请求工具 ,它可以替代浏览器和终端来发起 API
请求,并且可以对返回的数据进行 JSON
格式的转换,直观简洁。
基本概念
Node(节点) 与 Cluster(集群)
Elastic
本质上是一个分布式数据库,允许多台服务器协同工作,同时每台服务器可以运行多个 Elastic
实例。每个 Elastic
实例称为节点,一组节点称为集群。
Index(索引)
Elastic
中的 Index
(索引)相当于关系型数据库中的 dataBase
(数据库),当然也可以理解为是 table
(表)。每个 Index
的名字必须是小写的。下面的命令可以查看当前 Elastic
实例下的所有 Index
,包括每个 Index
的文档大小等信息。
$ curl -X GET 'http://localhost:9200/_cat/indices?v'复制代码
当然,你也可以在上面提到的 PostMan
中输入上面命令中的路由地址来查看。
Document(文档)
Index
中的每条数据记录被称为 Document
(文档)。多条 Document
构成了一个 Index
。所以说 Index
往小了看可以被当做一张表。Document
中的数据结构是以 JSON
格式表示的。
{ "auth": "Assassin", "work": "NodeJS全栈", "email": "告诉你才怪@qq.com",}复制代码
Type(分类)
Index
如果被看做是一个数据库的话,那 Type
就可以看做是这个数据库的表。注意,同一 Index
下的 Type
应该具备相似的结构(schema
),这一点是跟关系型数据库的区别。下面的命令是列出当前 Index
下的所有 Type
。
$ curl 'localhost:9200/_mapping?pretty=true'复制代码
多说一句,
ES
与关系型数据库的各个元素的对比:
Relational DB | Database | Table | Row | Colum |
---|---|---|---|---|
ElasticSearch | Index | Type | Document | Field |
Elastic中的数据类型
这里只列出常用的数据类型,其余的遇见再说
-
String:字符串类型,默认会被分词。其中包括
keyword
和text
两种子类型。keyword:存储数据时,数据不会被分词建立索引,可以被用来检索过滤、排序和聚合。如:'墙体钢结构',
keyword
会将它作为一个整体。text:存储数据时,数据会被分词建立索引,但如果该字段的数据没有分词的必要的话,使用
text
则会浪费存储空间,text
数据类型不能用来排序和聚合。如:'墙体钢结构',text
会将它切分为'墙体','钢结构'。分词器:只针对
text
类型。git
地址为 。其作用就是将文本按照一定的规则进行切分。安装方法:将下载的分词插件解压到根目录下的plugins
中,然后重启Elastic
实例。 -
数字类型:
- long:长整型,64 位存储
- integer:整型,32 位存储
- short:短整型,16 位存储
- byte:字节型,8 位存储
- double:双精度型,64 位存储
- float:单精度型,32 位存储
-
其他简单类型
- date:时间类型
- boolean:布尔类型
- binary:字节类型
-
复合类型
- array:数组类型
- object:json 对象类型
- Array[Object]:对象数组的嵌套类型
Index的mapping建立
Index
的创建包括了对每张表 Type
的定义。在 JavaScript
和终端中的创建方法如下:
- JavaScript
import elasticsearch from 'elasticsearch';const esClient = new elasticsearch.Client({ host: 'localhost:9200', log: 'error',});const settings = { number_of_shards: 5, number_of_replicas: 1,};const PromiseList = [ esClient.indices.create({ index: 'student', body: { settings, // index的一些设置 mappings: { // type person: { // type 的各个字段 properties: { sno: { type: 'long', }, name: { type: 'keyword', }, sex: { type: 'keyword', }, class: { type: 'text', analyzer: 'ik_max_word', search_analyzer: 'ik_max_word', fields: { raw: { type: 'keyword', ignore_above: 128, }, }, }, register: { type: 'date', }, }, }, ..... }, }, }), .....];PromiseList.map(p => p.catch(e => console.log(e.message)));.....复制代码
上述代码中,采用的是通过
Promises
来批量创建数据库的,如果是只创建单一的库可以用async await
。
- 终端
$ curl -X PUT -H 'Content-Type: application/json' 'localhost:9200/student' -d '{ mappings: { // type person: { // type 的各个字段 properties: { sno: { type: 'long', }, name: { type: 'keyword', }, sex: { type: 'keyword', }, class: { type: 'text', analyzer: 'ik_max_word', search_analyzer: 'ik_max_word', fields: { raw: { type: 'keyword', ignore_above: 128, }, }, }, register: { type: 'date', }, }, }, },}'复制代码
上面的代码中,创建了一个名为 student
的 Index
,其中包括一张 person
的表,表中包含四个字段:son
,name
,sex
,register
。
Index的删除
讲完创建,该讲删除了。删除很简单:
- JavaScript
import elasticsearch from 'elasticsearch';const esClient = new elasticsearch.Client({ host: 'localhost:9200', log: 'error',});Promise.all( [ 'student', ..... ].map(index => esClient.indices .delete({ index }) .catch(() => console.error(`delete fail: ${index}`)) ));复制代码
上述代码中,采用的是通过
Promises
来批量删除数据库的,如果是只删除单一的库可以用async await
。
- 终端
$ curl -X DELETE 'localhost:9200/student'复制代码
Elastic数据查询
Elastic
中常用的查询方法
search, get, count, mget, msearch 等
配置文件
import elasticSearch from 'elasticsearch';let _client = null;export default () => { if (!_client) { _client = new elasticSearch.Client('localhost:9200'); } return _client;};复制代码
单条记录的条件查询
单挑记录的条件查询的查询结构为一个类似 JSON
的对象
{ index: database_name, type: table_name, body: { query: { bool: { filter: { term: { 'field_name': value, }, }, }, }, },}复制代码
这是一个最简单的查询结构
当中的 filter
属性值为 Object | Array
, 其中 Array
为对象数组。如 [{term: {key: value}}, ...]
。
当然,查询不可能这么简单,还有其他的可添加的属性。
term & terms 过滤查询(匹配查询)
term
主要用于精确匹配哪些值,比如数字,日期,布尔值。一个 term
查询结构:
{ term: { key: value } }复制代码
与其类似的 terms
主要用来匹配多个条件的过滤查询。比如
{ terms: 'tag': [ 'react', 'vue', 'angular' ] }复制代码
range 过滤查询(范围查询)
range
过滤允许我们按照指定范围查找一批数据
{ range: { age: { gte: 18, lt: 28, } }}复制代码
范围的关键字:
-
gt: 大于
-
gte: 大于等于
-
lt: 小于
-
lte: 小于等于
在查询结构中的体现:
{ index: database_name, type: table_name, body: { query: { range: { age: { gte: 18, lt: 28, } } },}复制代码
range
和 term(s)
属于同级别的属性,所以可以作为 filter
数组属性的值
exists & missing 过滤
exists & missing
用于查找记录中是否存在或者没有某个指定的字段。
{ exists: { field: 'field_value' }}复制代码
exists & missing
和 term(s)
属于同级别的属性,所以可以作为 filter
数组属性的值
bool 过滤
bool
布尔逻辑查询,所包含的关键字:
-
must: 相当于 and
-
must_not: 相当于 not
-
should: 相当于 or
用法很简单,只需替换 filter
,当然,同 filter
一样的用法。
agg 聚合查询
对于这一块,语言描述上会存在一些理解上的差异。毕竟聚合这一块还是比较庞大的,so 为了更专业还是推荐度娘吧(等我再成长一些了再来做一下总结!!)
批量条件查询
批量条件查询就是对一组不同的查询条件集依次进行处理的查询过程,犹如一个批处理。
msearch 批量条件查询
msearch
就是将一般的条件查询的结构体放入到一个数组中,然后将这个数组再作为查询结构体。
{ body: [ { index: database_1, type: table_1 }, { query: { term: { field: value }, }, }, { index: database_2, type: table_2 }, { query: { bool: { must: { term: { field: value, }, }, filter: [ { term: { field: value } }, { term: { field: value } }, ], }, }, },}复制代码
从上面的结构体中可以看出,msearch
的查询结构体是吃从下标0开始,相邻两个元素作为一个单一查询结构体的数组结构。
mget 批量ID查询
这个方法适用于已知多个记录ID的批量查询
{ index: database, type: table, body: { ids, },}复制代码
其中 ids
为数组