转自:https://mp.weixin.qq.com/s/_jXdCPGsmcpMkEnFJ5VQ7A
仅作个人备份,浏览请看原文
之前给大家介绍过elasticsearch以及它的安装,今天我们来学习一下它的基本用法
中文分词器
首先我们来了解一下中文分词器,中文分词器有两种:一种是ik_max_word,一种是ik_smart,我们分别来看下他们对中文分词的拆分
ik_max_word分词器
采用ik_max_word分词器,我们看到我是中国人分成了:我、是、中国人、中国、国人
ik_smart分词器
下面我们采用ik_smart来进行分词,同样还是对“我是中国人”这句话来进行分词,我们可以看到,采用ik_smart分词器分成了:我、是、中国人
我们发现,ik_max_word是一种细粒度的拆分,而ik_smart则是一种较为智能的拆分,实际使用时可根据不同场景来进行选择
中文分词器的github链接,最新版本已经支持到6.6.2了,更新速度还是挺快的
https://github.com/medcl/elasticsearch-analysis-ik
Rest风格
我们知道,elasticsearch是一套基于Rest风格的api,我们刚刚是在Kibana可视化控制台中进行的请求操作,同样的,我们可以借助postman等工具对其发起rest风格的请求,如下,也得到了我们想要的结果,所以它的使用方式是很灵活的
不过在Kibana中有很强大的语法提示,使用起来更加灵活,它的底层实现还是rest请求,只不过帮我们都封装好了
Kibana首页,界面还是挺清爽的
Kibana主页,下面的操作都是基于Dev Tools可视化控制台里面操作的
基本概念
elasticsearch的一些概念
索引(indices):
数据库databases
类型(type):
Table数据表
文档(Document):
Row行,每一行数据就是一个文档,类似mysql查询出来的每一行数据
字段(Field):
Columns列,类似mysql的每个字段
索引库
创建索引库类似于创建数据库,我们创建一个名为test的数据库,语法:
PUT /test
{
"settings": {
"number_of_shards": 5
, "number_of_replicas": 1
}
}
创建成功图示
查询索引库
GET /test
删除索引库
DELETE /test
创建映射字段
在test数据库下面创建一张商品表,商品表里面有3个字段,分别是title、images、price
创建语法:
PUT /test/_mapping/goods
{
"properties": {
"title":{
"type": "text",
"analyzer": "ik_max_word"
},
"images":{
"type": "keyword",
"index": false
},
"price":{
"type": "float"
}
}
}
我们通过上面的语法,发现几个关键词,首先类型,文本类型有text和keyword,它们有什么区别呢,text类型的文本可以用来分词,不可用来聚合,而keyword的类型的文本不可分词,数据会作为完整的字段进行匹配,可以参与聚合
index代表是否索引,默认值为true,而一般图片的地址不需要检索的,所以index给设置为false
查看映射关系
GET /test/_mapping/goods
elasticsearch字段类型概述
一级分类 二级分类 具体类型
核心类型 字符串类型 text,keyword
整数类型 integer,long,short,byte
浮点类型 double,float,half_float,scaled_float
逻辑类型 boolean
日期类型 date
范围类型 range
二进制类型 binary
复合类型 数组类型 array
对象类型 object
嵌套类型 nested
地理类型 地理坐标类型 geo_point
地理地图 geo_shape
特殊类型 IP类型 ip
范围类型 completion
令牌计数类型 token_count
附件类型 attachment
抽取类型 percolator
添加数据
添加一条数据:
POST /test/goods
{
"title":"小米手机",
"images":"http://img.xiaomi.com",
"price":2999.5
}
查询所有数据:
GET /test/_search
{
"query": {
"match_all": {}
}
}
根据id查询数据:
GET /test/goods/HHzUuWkB96yUdC__j7MfGET
修改数据
根据id修改数据:
PUT /test/goods/HHzUuWkB96yUdC__j7Mf
{
"title" : "中米手机",
"images" : "http://img.xiaomi.com",
"price" : 3999
}
put功能很强大,如果id不存在,则是新增数据
PUT /test/goods/123565
{
"title" : "锤子手机",
"images" : "http://img.chuizi.com",
"price" : 1888
}
我们可以看到,result的返回结果,如果是修改数据,返回的updated,如果是新增数据,返回的是created,很灵活,可以代替post添加数据的功能
删除数据
根据id删除数据:
DELETE /test/goods/HHzUuWkB96yUdC__j7Mf
match查询
我们现在检索小米手机
GET /test/_search
{
"query": {
"match": {
"title": "小米手机"
}
}
}
但是我们仔细看结果,咦?为什么华为手机,锤子手机都搜索出来了,这里注意了,我们存储的时候需要分词,搜索的时候也需要分词,我们虽然是搜索小米手机,实际上elasticsearch是拿着小米、手机这两个词去库里面检索的。所以有小米或者手机这两个词的都被检索出来了
那我们就想搜索小米手机怎么办呢?我们可以采用下面的方式(用and关系,operator指定为and)
GET /test/_search
{
"query": {
"match": {
"title": {"query": "小米手机","operator": "and"}
}
}
}
match_all查询
查询所有数据,这个前面接演示过,这里不再赘述了,语法格式如下:
GET /test/_search
{
"query": {
"match_all": {}
}
}
词条查询
我们用term来查询小米手机
GET /test/_search
{
"query": {
"term": {
"title": {
"value": "小米手机"
}
}
}
}
我们发现,词条查询居然查不出小米手机,这是为什么呢?这是因为词条查询是将小米手机作为一个整体去数据库里面查询,而数据库里面的title字段都是分过词的,拿着整体去匹配分过词的数据,当然是查询不到啦!所以词条查询一般应用场景是用来去查询那些不分词的字段,例如:价格,图片地址
指定返回字段
有的时候,我们可能不需要所有的字段都返回,那我们可以用source来指定需要返回的具体字段
GET /test/_search
{
"_source": ["title","price"],
"query": {
"match": {
"title": "小米手机"
}
}
}
还有另外两种变种写法:
写法一(includes包含需要返回的字段):
GET /test/_search
{
"_source": {
"includes": ["title","price"]
},
"query": {
"match": {
"title": "小米手机"
}
}
}
写法二(excludes排除需要返回的字段):
GET /test/_search
{
"_source": {
"excludes": ["title","price"]
},
"query": {
"match": {
"title": "小米手机"
}
}
}
模糊查询
有一个场景,用户想搜索apple手机,但是不小心输入成applo,怎么办呢?别急,模糊查询fuzzy派上用场啦!
GET /test/_search
{
"query": {
"fuzzy": {
"title": "applo"
}
}
}
我们看到了,即使用户输错了,我们仍然可以查询出来
指定范围查询
查询价格在3000-5000范围内的手机:
GET /test/_search
{
"query": {
"range": {
"price": {
"gte": 3000,
"lte": 5000
}
}
}
}
布尔查询
查询商品名为小米手机,同时价格在1000-5000范围内的商品
GET /test/_search
{
"query": {
"bool": {
"must": [
{"match": {
"title": {"query": "小米手机","operator": "and"}
}}
],
"filter": {
"range": {
"price": {
"gte": 1000,
"lte": 5000
}
}
}
}
}
}
排序
查询商品名称为手机的商品并按照价格升序排序:
GET /test/_search
{
"query": {
"match": {
"title":{"query": "手机"}
}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
总结
基本的查询介绍完毕,下篇将着重介绍一些高级查询用法