elasticsearch text fielddata_ElasticSearch的API使用

前言:之前写过如何安装ElasticSearch(以下简称ES)以及简单的crud的使用实例的博客,不过ElasticSearch的版本变化太快,像之前的5.6版本使用的TransPortClient目前已经无法使用了,官方的API变化较快.最近工作中需要用到ES作为查询的中间件,项目组长决定使用7.4.2最新版本,在项目中如何使用ElasticSearch整个任务交给了我,经过几天的研究(瞎折腾),终于把基本的使用方法搞明白了,因为网上关于7.4.2版本的API使用说明实在太少,所以我决定整理成一篇博客发出来~

一:ES的基本数据类型

ES的数据类型大概可以分为以下几种,值得注意的是ES是没有java中的list或者set这个概念的,每种类型都天然的支持list多层数据,但是如果设置为list的类信息,就必须将数据类型指定为nested,详情看以下介绍:

3296af9c645abb0b0b857c492982ebcc.png

二:基本的查询语言

es的查询语言叫做QSL,也就是它的查询语言,和mysql的sql概念类似,所有的查询都需要去匹配相关的QSL才能得到信息,同时QSL又有自己的语法,必须遵守语法才能得到我们想要的信息,接下来我们就来解析一下QSL.

1.1:Index

Index是ES的数据库的概念,所以一开始就必须建立索引,在7.4.2版本中已经去除了type的概念。所以不需要建立type,在ES中创建一个index也是十分简单的,按照官方的文档,注意索引的名字只能是小写,不能是大写,否则会报错,建立一个index的QSL如下,使用PUT请求的格式(注意PUT要大写),斜杠后面跟上index的名字,然后在设置里写上分片和副本的数量(如果不指定的话,ES会默认设置为shards和replicas为1)。关于如何定义shards和replicas的数量,请参考xxx.

79e8023da82bbbf66c433a6a96e37fd6.png

1.2:mapping

建立mapping就好比是mysql中创建表结构,我们要来表达业务必须在mapping里面创建具体的数据properties(properties就好比是mysql表中的字段概念),完整的创建一个mapping的结构如下,使用PUT请求,在proerties中声明field的类型,在type中声明数据类型,需要注意的是es的mapping创建之后无法修改,如果需要修改需要重新建立index,然后reindex迁移数据,所以创建mapping之前一定要考虑清楚具体的业务

67c3877ee23b5496927366b316f7bf84.png

1.3:创建index的同时创建mapping

在1.1和1.2中创建index和mapping是分开的,其实也可以一步到位同时创建index和mapping,使用如下语法,在index中声明mappings,具体的创建结构和1.2的mapping保持一致

3776d499b916b414cd5a4ff74f97c449.png

实例:我们来创建一个人,这个有年龄、名字、出生日期等属性(以下命令可以在kibana中直接使用,详情请安装kiana)

PUT  /person
{
   "settings" : {
        "index" : {
            "number_of_shards" : 2, 
            "number_of_replicas" : 1
        }
     },
    "mappings":{
        "properties":{
           "id":{
                "type":"keyword"
             },
            "name":{
               "type":"text",
               "analyzer": "ik_max_word"
            },
            "age":{
                "type":"integer"
            },

           "phone":{
                "type":"text"
            },
           "birthday":{ 
              "type":"date" 
            }, 
         
          "position":{ 
             "type":"geo_point" 
            }, 
 
         "provinceId":{ 
            "type":
             "integer" 
         } 
       } 
    } 
 }

以下结果表示创建成功:

4dde428e552392eeece668299677abb1.png

1.4:match

match是模糊匹配查询(和fuzzy不同),根据分词器(如果创建mapping没有指定分词器,Es将会采取默认的分词器:standard,standard分词将会把匹配的词组分成单个的字,而不是短语)将指定的query查询的语句进行分词匹配,如下的match是在index中查询messae字段中包含test字段的短语:

081af47d270d783e1e0265ebfe7302f8.png

实例:查询person中name为周星驰的文档:

a8c43bb3fb9e26fb305f4464adf5eadd.png

以为name字段指定了分词器为”ik_max_word“,在分词器下”周星驰“三个字会进行拆分,只要匹配到任一词汇就会返回,这里需要注意不是全部匹配

98f0f20461c334081ff7419e2073605b.png

e7d4f018061d3373fd8784df1a306836.png

匹配结果:

8f7359cfe8d54451465dfa491e6c252f.png

1.5:match_pharse

match_pharse属于短语匹配,要求查询的词句和匹配的短语顺序必须一致,并且是连续的,但可以设置 slop 值来指定查询项之间可以分隔多远的距离

实例:

25c247c3140f5114a0d4b47cbee4a4cf.png

这里故意颠倒了词组顺序,可以看出来没有匹配到任何结果:

d4c98f17cc2b50962bc9418f6190f968.png

1.6:fuzzy

fuzzy查询的时候,不会根据分词器匹配,只会进行拆分,比如查询的是"周大驰",在分词器下(也就是match中)是无法匹配到单个词的,因为它不是一个短语,但是在fuzzy中是可以匹配的,并且fuzzy支持模糊和一定的容错查询匹配,因为它做的是匹配词的拆分,并不是短语。

324ec1bc2ad8715d7faf21106c04156d.png

返回的结果:

6c8b27832dc2358899ac0ce728c8517f.png

1.7:regexp

正则表达式匹配,该匹配模式下我们可以按照正则表达式的符号去匹配具体的值,比如name字段,可以包含有.和*去正则匹配具体的值,?表示任一字符,*表示所有字符,还有其他的正则符号都可以使用,详情参考https://www.elastic.co/guide/en/elasticsearch/reference/6.8/query-dsl-regexp-query.html#regexp-syntax

35f846d78100d29567d4fa17ed01e76d.png

匹配手机号以1到9之前的开头,并且第二位是3最后一位是0或者1的手机号

41ad4c7ba063bd64f5f3a579ebec6e03.png

1.8:wildcard

通配符匹配,wildcard和regexp类似,不过它们也有不同之处。regexp的实际匹配能力要大于wildcard,在进行简单的匹配时候,比如名字的*或者?的简单普通匹配,建议使用wildcard而不是regexp,wildcard的效率要高于regexp,regexp可以实现更为复杂的场景,但是效率低一些,通俗的说wildcard是regexp的简化版本.

8917b5ed1724380c1e7f82a8df179731.png

这里采用通配符匹配手机的电话号,*表示多个字符,可以看到匹配结果

fc97865de5e6b40f8d0f145206f47d26.png

1.9:multi_match

多字段匹配,比如在查询test这个值的时候我们不仅需要在A这个字段中查询,同时它也有可能存在B中,按照普通的写法你可能需要写两次查询,但是使用了multi_search只需要指定具体的fields就可以实现多字段查询

实例:同时在age字段和phone字段搜索包含38这个数字的文档

bb4a852a3c2a99107bdbf8af131cbc76.png

658d5aa3f3cc9d73c7e7e1324b5f42fa.png

2.0:term

term的英文含义表示是:精确的意思,在term查询中,表示做的是精确查询,整词匹配,不会对所匹配项进行拆分。举个例子在field字段中查询Yrion这个词,那么它不会进行拆分,直接以整词Yrion进行匹配,如果能查询到就命中该文档:

b67569485c9c7bd6426ff2eb363c68f8.png

这里查询的name为周星星,term不会分词,因为没有任何文档的name匹配,所以不会命中任何结果

50a2ed8cb6685eea3b3b71066871a895.png

2.1:terms

terms和term的区别就是terms允许匹配多个值,而term只允许匹配一个值,在进行多值匹配的场景中可以使用terms,terms匹配到其中任何一个值就会认为整个文档是匹配的,terms多个值如果多个都匹配会返回所有文档

实例:查询age为24、66的任一值,查到就返回文档,可以看出命中了两个文档

5e538b60c0d97e5596920a102866153f.png

27865d69d2c621177a9a9a32bb3437aa.png

2.2:range

range表示一个区间范围查找,这个范围可以是日期或者数值,类似于mysql中的between,不过ES的range比较灵活和明确,可以指定两个边界是否包含。如下的查询表示寻找age在10和20之间的数据

实例:查询age为20到30区间所有文档,include_lower表示是否包含边界最小值(true表示包含),include_upper表示是否包含边界最大值(true表示包含,false表示不包含)

8c6087e21e73ada1d1df6b4f315834d1.png

返回结果:

86d20af7fe1c7ac1509e8f4968f90985.png

2.7:bool

bool表示逻辑关系的查询,must表示and的关系,should表示or的关系,mustNot表示not的关系

实例:查询省份在北京(provinceId:2)或者年龄在10-60岁之间的并且名字不姓周的人:

ddbca6dcff6ab14c8db205bf2bf17ba2.png

223f712cb0c72e08438fb24d504275bb.png

2.8:geo

geo表示根据经纬度进行地理位置的查找,ES提供了地理位置的三种查找方式:①以指定的经纬度为圆心,距离为半径画圆搜索周围区间落到的点 ②:以指定的经纬度组成多边形(geo_shape),查找矩形中的点。不过需要注意的是geo搜索需要将field指定为geo_ponint的数据类型,否则在查询的时候会报错.以下表示以-70和40为中心圆点,查找距离为12km的文档,如果符合这个距离的条件,就会hit到文档

a570e18a8836285647af5d076feead07.png

以经度为47.998,维度为63.841为中心寻找周围5公里的位置:

2f798766dff3cf4faf2b291143473199.png

2.9:sort

sort表示排序,ES提供了三种排序方式①:按照文档的得分来排序,ES会自动根据查询的条件来匹配文档,每个文档命中值就会有一个score值,可以按照score值进行排序 ②按照指定字段的值可以倒序,也可以正序③按照指定地理位置的距离来进行排序,这里需要注意的就是在排序字段上如果是text类型就必须开启 fielddata,而keyword可以直接用来排序,所以建议如果要给字段排序就最好声明为keyword类型

0dab4a5347e0a133ab47280418f3db12.png

这里指定了匹配所有文档,然后按照年龄的降序排序desc表示降序,esc表示升序

e93bd7199b5e7bc15cc396e69e9952bf.png

3.0:page

ES默认返回的条数值为10,如果想改变返回的条数值,可以指定size的大小,也可以指定from的起始位置,也就好比mysql中的pageIndex,size是pageSize,对应于mysql中的limit 0,5,则在ES中是from 0 to 5:

5eb154423af52b3b83c0298e74c59eb1.png

这里选择返回两条数据,表示分页的大小为2,可以看出最终的结果是只返回了两条数据:

baec98991e6e3edffeb4c37f9d7773b2.png

二:使用实例

首先来定义这样一个场景,有很多人的文档人的属性有年龄、名字、爱好、职业、出生日期、地理位置等属性,我们需要找到符合指定条件的人,这里就需要用到查询的方式,我们首先来创建person整个index,然后创建mapping结构,之后put进去数据,可能还会涉及到person的修改或者删除,之后可以建立复杂的查询来模拟现实的业务场景.具体的api可以查询官方文档,API就不做说明了,git地址的代码里都有,就不做搬运工了

接口已经写好,结合前端可以直接实现增删改查,整体架构也比较简单:

7de9b4fc822f38168535d7650d3f1698.png

三:总结

本篇博客总结了ElasticSearch的一些基本查询语法,并给出了实际查询的例子,只要是学会了语法,查询的API很容易学会,具体的代码也在git中给出,作为一款全文检索引擎,ES的效率和使用的场景都可见一斑,ES基本属于程序员必须掌握的一项学习技能。目前开源的搜索引擎还有阿里的opensearch,两者各有千秋~opensearch以后有机会研究,总之在全文搜索的路上,ES基本是必经之路,加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值