ES入门到写DSL:我只会Mysql语句,不会es语句怎么办?
Posted 想找工作的狗蛋儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES入门到写DSL:我只会Mysql语句,不会es语句怎么办?相关的知识,希望对你有一定的参考价值。
es一点都不会,但是分到一个数据统计的功能。数据都在es中,利用es查询筛选出来结果集,然后利用web服务进行显示。于是就·············又掉了好多头发。
Elasticsearch基本概念
Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式。
#es一条数据存储形式就如下所示:
{
"_index": "user_info",
"_type": "_doc",
"_id": "1",
"_version": 1,
"_score": 0,
"_source": {
"name" : "Xiang",
"sex" : "男",
"age" : 23,
"birthDate": "1998/05/01",
"address" : "北京"
}
}
这里还要了解几个有关ES的其他的基本概念
倒排索引(Inverted Index)
该索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。
为什么称之为倒排呢?在mysql查找数据 就是通过 id索引去查询该记录的值,这是正常思维。而es却不是这个做的,它是通过属性值确定记录的具体位置。
es将数据分词然后针对单词生成索引,流程如下图:
1.es分词
2.针对单词出现的位置创建索引,
3.去重统计次数
4.排序得到索引表
5.查询hello,遍历索引表。
6.找到索引位置确定数据的位置 1,2
7.就能得到hello world,以及hello elasticsearch
Elasticsearch中的核心概念
索引 index
一个 索引 应该是因共同的特性被分组到一起的文档集合。
类型 type
数据可能在索引中只是松散的组合在一起,但是通常明确定义一些数据中的子分区是很有用的。
文档 document
一个对象被序列化成 JSON 并存储到 Elasticsearch 中被称之为文档,并指定了唯一 ID。
字段 field
json文档中一个键可以称之为一个字段。
映射 mapping
为了能够将时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串, Elasticsearch 需要知道每个域中数据的类型。这个信息包含在映射中。
ps:其实就是关系型数据库的表结构。
与传统的关系型数据库不同的是 当你索引一个包含新域的文档—之前未曾出现-- Elasticsearch 会使用 动态映射 ,通过JSON中基本数据类型,尝试猜测域类型。不需要我们开发人员自己创建映射,也就是不用我们在关注各个表字段的类型。
与Mysql对比
ES 基本操作
-
创建索引
格式: PUT /索引名称PUT /es_db
类似Mysql中的创建数据库
creat Database 名称 -
查询索引
格式:GET /索引名称GET /es_db
-
删除索引
格式: DELETE /索引名称DELETE /es_db
类似Mysql中的删库
drop database 数据库名称 -
添加文档
格式: PUT /索引名称/类型/idPUT /es_db/_doc/1 { "name" : "Xiang", "sex" : "男", "age" : 23, "birthDate": "1998/05/01", "address" : "北京" }
类似Mysql中的插入一条新字段
insert into table_name。
但其实还是有区别的,因为在Mysql中,插入一条记录需要 建一个表,以及表结构规定好。
另外值得注意的是在es中有type有一个初始的_doc,而表结构则会在插入一个文档时候会自动创建表的映射,这点在之前映射的概念也提到过。 -
修改文档
格式: PUT /索引名称/类型/idPUT /es_db/_doc/1 { "name" : "sun", "sex" : "nv", "age" : 23, "birthDate": "1998/05/01", "address" : "北京" }
这里更新是和添加一样的命令,当存在就会更新文档内容,如果不存在就会新添加一个文档
注意:POST和PUT都能起到创建/更新的作用
1、需要注意的是PUT需要对一个具体的资源进行操作也就是要确定id才能进行更新/创建,而POST是可以针对整个资源集合进行操作的,如果不写id就由ES生成一个唯一id进行创建==新文档,如果填了id那就针对这个id的文档进行创建/更新
2、PUT只会将json数据都进行替换, POST只会更新相同字段的值
3、PUT与DELETE都是幂等性操作, 即不论操作多少次, 结果都一样 -
查询文档
格式: GET /索引名称/类型/idGET /es_db/_doc/1
类似Mysql中的根据主键id查记录
select * from table where id = 1 -
删除文档
格式: DELETE /索引名称/类型/idDELETE /es_db/_doc/1
类似Mysql中的根据主键id删除一条记录
delete from table where id = 1
基本的概念以及操作已经讲解完成,下面我们来研究es更加实用也相对比较复杂的查询吧。
无条件查询
select * from table
GET /data_analysis/_search
{
"query": {
"match_all": {}
}
}
data_analysis 就代表着你要搜索的索引库,_search 代表着 select。而query代表where ,而much_all代表着全部查询。
GET /data_analysis/_search
其实这样写也是可以的,在kibana中直接这样运行也是查询所有。
拓展
有人问了,我只想查询出来指定的列 select id,name from table
,那 es怎么办啊?
GET /data_analysis/_search
{
"_source": ["id","name"],
"query": {
"match_all": {}
}
}
若带有 "_source"字段,会查询出指定的字段信息。若不带有此字段默认是查询所有字段。
组合条件查询
单个条件就不介绍了,实际开发都是复合多条件查询。介绍DSL查询语句之前,先介绍一个各个字段。
must :各个条件都必须满足,即各条件是and的 关系
should :各个条件有一个满足即可,即各条件 是or的关系
must_not :不满足所有条件,即各条件是not的 关系
精确匹配
**term **: 单个条件相等 即条件 =
terms : 单个字段属于某个值数组内的值 即条件in()
range : 字段属于某个范围内的值 即between and()
exists : 某个字段的值是否存在 及not null
模糊匹配
match: 通过关键词模糊匹配条件内容 即 like ‘%关键词%’
prefix : 前缀匹配 即 like ‘前缀%’
上面的其实就是DSL语法定义各中条件查询的API,直接上案例吧。
案例:
es中有一个 test_csdn索引库,包含了以下几个字段:
字段名称 | 字段类型 |
---|---|
name | text |
sex | text |
address | text |
work | text |
age | long |
先查询一下看看数据,总共8条数据。hits就是命中的数据的数组,一个{}里是一个完整的文档(就是数据库一行数据)。
需求1 :查询所有name叫“wang”的人的信息
select * from test_csdn where name = 'wang'
GET /test_csdn/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "wang"
}
}}
]
}
}
}
需求2 :查询所有name叫“wang”和“qi”的人的信息
select * from test_csdn where name in ('wang','qi')
GET /test_csdn/_search
{
"query": {
"bool": {
"must": [
{"terms": {
"name": [
"wang",
"qi"
]
}}
]
}
}
}
需求3 :(加点难度)查询所有age 10-25 岁的,work 为 开发 以及 address 在北京 的
select * from test_csdn where age between 10 and 25 and work like '%开发%' and address like '北京'
GET /test_csdn/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"gte": 10,
"lte": 25
}
}
},
{
"match": {
"work": "开发"
}
},
{
"match": {
"address": "北京"
}
}
]
}
}
}
需求3 :(加点难度) 查询所有age 26 或者 21 岁的,work 为 开发或者运维 以及 address 在大连(嵌套查询)
select * from test_csdn where (age = 26 or age = 21)and (work like '%开发%' or work like '%运维%')and address like '大连'
GET /test_csdn/_search
{
"query": {
"bool": {
"must": [
{"bool": {
"should": [
{"term": {
"age": {
"value": "26"
}
}},
{"term": {
"age": {
"value": "21"
}
}}
]
}},
{
"bool": {
"should": [
{"match": {
"work": "开发"
}},
{"match": {
"work": "运维"
}}
]
}
},
{"match": {
"address": "大连"
}}
]
}
}
}
怎么样是不是有点晕头转向,一时间看不懂。来我们细细剖析一下:首先需求中,age ,word以及 address 的限制其实都是并列必须满足,也就是and。所以我们的最外层用一个must。
select * from test_csdn where (age限制)and (word限制)and address限制
这样折叠起来看是不是更加清晰了,也就说每一个{}限制的条件都是and连接。
然后我们拆分看age限制:
(age = 26 or age = 21)
是or,所以DSL应该用should对吧,should,must都需要一个bool连用。
这样的话是不是在拆分word就很清晰了:
(work like '%开发%' or work like '%运维%')
所以及时再复杂的嵌套查询,其实DSL语句也不是很难对吧。
es分页查询
其实es默认就是使用分页的,默认只会显示10条数据。我们想要修改设置的话就要声明from和size指定值。
from就是从第几条数据开始,szie就是页的大小。
这样就是只会查看0-4 的数据也就是第一页,第二页就应该是from:5,size是不变的。
计算页码公式一般是 from:size*(第几页 -1)
排序
利用age字段降序排列
"sort": [
{
"age": {
"order": "desc"
}
}
]
分组聚合
想要统计以age分组,各个年龄的人数
"aggs": {
"work_groupby": {
"terms": {
"field": "age"
}
}
}
好了好了,就这样吧。本篇文章可以让你快速入门进行使用es,但是想要真正的了解和熟悉使用es还是要潜心慢慢去研究的。
以上是关于ES入门到写DSL:我只会Mysql语句,不会es语句怎么办?的主要内容,如果未能解决你的问题,请参考以下文章