Elasticsearch 官方网站:
Elastic -> 开始
安装
启动
Elastic -> 认识
基本概念
数据类型
Elastic -> 数据库和表的建立
Index 的 mapping 建立
Index 的删除
Elastic -> 数据查询
单条记录的条件查询
批量条件查询
安装
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 请求工具 PostMan https://www.getpostman.com/apps , 它可以替代浏览器和终端来发起 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 地址为 https://github.com/medcl/elasticsearch-analysis-ik . 其作用就是将文本按照一定的规则进行切分. 安装方法: 将下载的分词插件解压到根目录下的 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 为了更专业还是推荐度娘吧(等我再成长一些了再来做一下总结!!)
ES 的 aggs https://www.cnblogs.com/duanxz/p/6528161.html
批量条件查询
批量条件查询就是对一组不同的查询条件集依次进行处理的查询过程, 犹如一个批处理.
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 为数组.
文 / Assassin 就是我
来源: https://juejin.im/post/5bf6108ae51d455e11316241