ElasticSearch
一、ElasticSearch简介
1.1 什么是ElasticSearch
ElasticSearch简称ES,其中Elastic
从名字里我们可以知道,ES的特点就在于灵活的搜索,其实ES本身就是一个全文搜索引擎。
1.是一个开源的高扩展的分布式全文搜索引擎。
2.它可以近乎实时的存储,然后检索数据,延迟很小。
3.本身扩展性很强,可以扩展到上百台服务器(分布式搜索),处理PB级别的数据。
4.ES使用java开发,底层是基于Lucene作为核心来实现所有索引和搜索功能的,提供了一套RESTful风格的api使得全文搜索变得简单,隐藏了Lucene得复杂性,更易于使用和扩展。
注意:Lucene只是一个库,想要使用它,必须要了解它的原理,对于很复杂的搜索,使用起来就非常的难受,ES就是基于Lucene库进行了封装和改造,使得开发人员对于复杂的搜索也极其的简单。
1.2 ES中的核心概念
1. Node(节点)
我们使用ES的时候是在一台服务器上安装ES,然后再启动,这时ES就可以使用了,默认访问地址是(http://localhost:9200,其实这就是一个节点(Node),由于我们前边说到,ES是分布式的,所以我们可以在多台服务器上安装ES,这样我们就有了多个节点,一般的话,一台服务器上只部署一个节点,当然如果我们的服务器性能比较优秀,就可以多部署几个ES的实例,默认ES实例占用9200端口,我们可以把其他的ES实例设置成9201、9202等端口,然后分别启动,这样我们就可以在一台机器上启动三个ES节点了。/)
2.Cluster(集群)
上边说的多个节点组合在一起就形成了一个集群,在每个ES节点中,我们可以通过配置集群的名称来使各个节点组合在一起,成为一个集群。当某些节点的集群名称一样,ES会自动根据配置文件中的地址找到这些节点,然后就自动组成一个集群了,这一切都是ES自动来完成的,所以说ES的分布式扩展性很强,在这些节点中可以随时增加和删除节点不用费一点精力。
综上所述:一台服务器也可以有多个节点,所以我们就会看到有些大型企业所说的ES100多个集群,200台服务器,500多个节点什么的。
3.Shard(分片)
当我们有大量的文档时,倘若我们都存在一个节点(或服务器上),由于机器性能的有限,就无法足够快的响应客户端你的请求,这时我们就可以把数据分成较小的分片,每个分片放在不同的服务器或节点上,这样,当你查询的数据有多个分片时,ES就会发查询请求同时分发到这些分片的节点上,之后每个服务器独自查询较小的数据分片,然后ES再把数据结果组合起来,因为是并行,相当于多线程了,这样吞吐率就非常高,对用户来说,速度也就很快了。
4.Replia(副本)
副本,顾名思义就是复制,默认每一个数据集都会被分成几个分片,我们把这些分片叫做主分片,副本就是把这些分片在复制一份,复本是按份数来衡量的,假设我们的一个数据集有5个分片,那么一份副本也会有5个分片,二份副本就是10个分片,加上5个主分片,我们就把这个数据集分成了15个分片,副本是主分片的精确复制,当我们的副本多的话,我们就可以把这些副本分片再分布到其他的服务器上,这样就显然提高了我们的性能,另外,很多服务器上都有我们的分片,假设我们的服务器宕机了,ES也能利用分片快速恢复我们的数据,即使我们停掉了几台机器,ES也能快速的利用副本保证数据分片的完整性,真正的实现了高可用性。
- 关系性数据库中的(Database),对应ES中的索引(Index)。
- 一个数据库下有N张表(Table),对应一个ES索引中有N个类型(Type)。
**注意:ES6.x中已经限制了一个Index中只能有一个Type类型,**使得一个Index就是一个类型,ES7.x中将取消Type的概念,ES8.x中将完全移除。参考链接:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/removal-of-types.html
不过问题不大,以后我们就认为一个Index就是一个类型就行了。
3.在一个关系型数据库中,我们会定义表的接口,什么类型啊,长度啊,还有表之间的关系,对应ES中的Mapping,ES中Mapping类定义Type的字段类型,处理规则什么的。
4.数据库中的insert、update、detele、select对应ES中的api Put/Post、Delete、Get请求。
1.3 ES的特点和优势
1.分布式实时文件存储,可将每一个字段存入索引,进行全文搜索。
2.实时分析的分布式搜索引擎,ES将新数据建立索引,可以在很短的延迟后就能搜索到新数据,近乎实时的搜索,相比于传统数据库来,建索引的过程就很慢,就不能达到很实时的搜索。
3.ES中的数据负载均衡和路由都是自动完成了,开发人员完全不担心某台服务器数据非常大而其他服务器数据量非常小的情况,造成我们的资源利用率不高。
4.可以扩展到上百台服务器,处理PB级别的数据的搜索。
1.4 为什么要使用ES
**但凡一个东西流行火起来,肯定有他的好处,而且也是经过很多实践的,为什么要用,因为大公司都在用,这玩意确实不错。 **举几个例子:
1.2013年初,GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使用ElasticSearch搜索20TB的数据,包括13亿文件和1300亿行代码”。
2.维基百科:启动以elasticsearch为基础的核心搜索架构。
3.SoundCloud:“SoundCloud使用ElasticSearch为1.8亿用户提供即时而精准的音乐搜索服务”。
4.百度:百度目前广泛使用ElasticSearch作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部20多个业务线(包括casio、云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大100台机器,200个ES节点,每天导入30TB+数据。
博主本着求真务实,对广大博友负责任的态度,郑重声明:
注意:以上例子都是从网上搬过来的,也不知道是真的假的,估计不会骗人吧,大家都说厉害,那就很厉害了,反正自己也没测试过。
二、ES的安装
2.1 下载
下载地址:https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.6.2.msi,下载windows的安装版本,一般的我们学习使用一个东西都是先从windows上开始,这样操作和学习都比较方便。
注意:因为ES是java开发的,所以需要安装jdk,安装完之后要配置环境变量,这个就不再赘述了,不会的可以从网上搜索怎么配置。
2.2 安装
2.2.1 安装完之后来到es的目录,如下,这是我的目录 F:\Dev\elasticsearch-6.6.2
2.2.2 进入bin目录,打开命令行(ps:在地址栏直接输入cmd,敲回车,就会在当前目录打开一个命令行窗口,这个操作估计很多人不知道)
2.2.3 在命令行输入elasticsearch-service.bat install 把ES安装为服务
2.2.4 打开任务管理器,查看ES是否启动,没有启动,就启动
2.2.5 直接访问 http://localhost:9200/ ,浏览器出现如下所示,表明成功
三、开始使用ES
3.1 文档操作
3.1.1 索引操作
建立索引就相当于我们的创建数据库,创建数据库就要随之的创建表结构,插入数据什么的。这一系列的过程和传统关系型数据库是一致的。
创建索引:Put http://localhost:9200/users 建立一个名称为users的索引(数据库)返回结果如下:
获取索引信息:Get http://localhost:9200/users 输出结果如下:
3.1.2 设置Mapping
关于Mapping详细设置参看http://www.baidu.com)。设置Index的Mapping,也就是设置数据的表结构
先删除索引:Delete http://localhost:9200/users
重新创建索引:Put http://localhost:9200/users 并提交一下参数,content-type:application/json
{
"mappings": {
"doc": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"age": {
"type": "long",
"index": false
},
"gender": {
"type": "keyword"
}
}
}
}
}
name:text类型,会进行分词,支持模糊检索。
name.keyword : 这相当于是嵌套了一个字段,keyword类型,只能精确匹配,不支持分词。超过256字符长度不索引,也就没法搜索到。
age:long类型,支持精确匹配。
gender:keyword类型,只能精确匹配,不支持分词。
3.1.3 插入文档
插入文档:Put http://localhost:9200/users/doc/1,其中users代表索引库名称,doc代表类型,1代表id,输出结果如下:
{
"name":"fuheng",
"age": 22,
"gender":"man"
}
3.1.4 获取文档
根据id获取文档:Get http://localhost:9200/users/doc/1,和添加一样,只不过Http方法换成了Get,输出结果如下:
3.1.5 删除文档
根据id删除文档 Delete http://localhost:9200/users/doc/1,和添加一样,只不过Http方法换成了Delete,输出结果如下:
根据query来删除文档,向数据库插入两条数据如下:
根据年龄删除数据:Post http://localhost:9200/users/doc/_delete_by_query ,删除年龄为28的记录,提交的数据如下:
{
"query":{
"match":{
"age": 22
}
}
}
3.1.6 更新文档
覆盖更新(先删除后添加):Put http://localhost:9200/users/doc/1,可以看出,ES先删除了所有的字段,最后只把age字段更新了上去,相当于我们之前的文档被删除了(不知道这种更新有什么用?)**?_?
部分更新(不删除,更新相应字段)Post http://localhost:9200/users/doc/2/_update,如下, 先添加一个新文档,然后更新age字段和gender字段:这才是我们想要的。
结果如下:
根据查询条件更新:http://localhost:9200/users/doc/_update_by_query,不过提交的数据要按脚本来更新,目前官方文档没给出其他例子。
其中ctx._source指源文档,下边表示把源文档的age赋值更新为5:
3.1.7 批量获取
批量获取文档(不指定索引库):**http://localhost:9200/_mget,*这里我们没有在url里边指定索引库,但是在提交的数据里指定了索引库和类型:
这里我们指定了获取索引库users下的类型为doc的且id为1的文档,和索引库为orders类型为order的且id为1的文档,返回值如下:
批量获取文档(指定索引库或者类型):*http://localhost:9200/users/_mget 或者 *http://localhost:9200/users/doc/_mget*
可以直接传ids参数作为id的集合来搜索:
3.1.8 批处理操作
ES允许我们在一次请求中做多种操作,比如在一次请求中同时进行增删改查操作:
批处理操作:http://localhost:9200/_bulk 下边进行了一个批处理操作,分别包含添加、删除、更新操作,
但是提交的参数必须是一行一行的json,且结尾必须又换行符,要这样ES才好处理,因为不是标准的json格式,这里PostMan识别json格式错误,但是问题不大。这里有个Json格式的坑,需要注意一下。
{"index":{"_id":3,"_type":"doc","_index":"users"}}
{"name":"bulk","age":33,"gender":"man"}
{"delete":{"_id":2,"_type":"doc","_index":"users"}}
{"update":{"_id":1,"_type":"doc","_index":"users"}}
{"doc":{"name":"bulk_update"}}
3.1.9 重建索引
重新建立索引,相当于数据什么的都拷贝一份:http://localhost:9200/_reindex
{
"source":{
"index":"users"
},
"dest":{
"index":"users_copy"
}
}
上边我们把users索引重新索引为users_copy,ES会为我们重新复制一份索引库。
更多查询参数和语法请查看:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/docs.html
3.2 查询操作
3.2.1 多索引和多类型查询
所有的查询api都可以用多索引、多类型的查询,多索引或者多类型之间用逗号隔开,如下:
Get /users/teacher,student/_search?q=name:sss 查询users索引下类型为teacher和student的数据,查询条件为name=sss。
Get /users,managers/teacher/_search?q=name:sss 查询users索引和managers索引下类型为teacher数据,查询条件为name=sss。
Get /_all/teacher/__search?q=name:sss 查询所有索引下类型为teacher数据,查询条件为name=sss。
Get /_search?q=name:sss 查询所有索引下所有类型的数据,查询条件为name=sss。
3.2.2 查询字符串查询
(URI Search)我们可以通过get方式,在url后边添加查询字符出的方式查询,如下:
http://localhost:9200/bank/account/_search?q=lastname:Mckenzie OR firstname:Amber&sort=account_number:asc,age:desc&from=0&size=5&_source=firstname,lastname,account_number,age
红色部分(查询):表示查询lastname=Mckenzie或者firstname=Amber的文档,OR表示操作符“或者”,类似的还有AND。
橙色部分(排序):表示按account_number升序排列,再按age降序排列,多个排序字段用逗号隔开。
蓝色部分(分页):分页获取。
黄色部分(投影):可以选择返回指定的字段,多个字段用逗号隔开。
更多查询参数和语法参看:
https://www.elastic.co/guide/en/elasticsearch/reference/6.0/search-uri-request.html
https://www.elastic.co/guide/en/elasticsearch/reference/6.0/query-dsl-query-string-query.html
3.2.3 请求体查询
(Request Body Search)我们依旧是通过get的方式请求:**http://localhost:9200/bank/account/_search,**设置content-type:application/json,提交以下数据:
{
"query": {
"match": {
"address": "Putnam Avenue"
}
},
{
"sort": [{
"account_number": "asc"
}]
},
"size": 5,
"from": 10
}
更多查询参数和语法参看:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/search-request-body.html
3.3 Query DSL
DSL指(Domain Specific Language 领域指定查询语言)。说白了也就是ES专门设计的查询语言,ES最关键的地方就是查询,各种千奇百怪奇形怪状的查询基本满足了我们开发中的检索的所有需求,这是ES中重点,下面我们就来看看。
3.3.1 Query and filter context
一个查询语句究竟具有什么样的行为和结果,主要取决于它在查询上下文(Query Context)还是在过滤上下文(Filter Context)两者的区别具体如下:
1.Query Context 查询上下文,执行时会计算文档是否匹配,并且还要计算文档的匹配度有多高,匹配度越高,"_score"分数就越高。
2.Filter Context 过滤上下文,执行时只关心文档是否匹配,不会计算匹配度(分数)。
下述查询中,bool中的must查询字句的最外层是query,所以它再query context中,而filter中的range查询是在filter context中,但是整体还是在query context中,查询结果会显示分数(”_score“字段),如下:
{
"query": {
"bool": {
"must": [{
"match": {
"address": "place"
}
}],
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}
而当我们去掉了must查询字句的时候,会出现一下结果,分数都为0,这说明只有filter context 时,不会做分数的评估。
3.3.2 Full Text Query(全文搜索)
这里的全文检索会对字段进行全文简单,包括模糊查询、分词查询、精确查询等。
ES默认会把所有字段都建成索引,字符串字段会默认被分词,作为全文检索,分词器使用的默认分词器,中文会一个字一个字的分词,英文会根据空格分成一个一个单词,之后会全部转换成小写存储,分词后就会形成一个一个的token(词条),后续ES的查询基本上就是根据每个字段的tokens查询的,token这个东西就很关键了,不同的分词器分成的token不一样,一个字段会分词成多个token,存放的是一个token数组,所以就会影响查询结果。
Match Query:全文查询中最主要的查询,包括模糊查询(会把查询关键字按空格隔开作模糊查询),指定分词方式(按分词器拆分成token)查询。查询时,会把查询关键字先做分词处理,然后再匹配字段分词的token数据。
Match Phrase Query:phrase是短语的意思,意思是把输入的关键字按整体来查询,先进行分词器分析,把分词器分析的结果按照词条的组合进行匹配,并且顺序也要一样。这个查询在英文中看起来就是短语查询。
比如查询关键字为:henan nanyang,那么查询的字段中需要完全包括henan nanyang 这个短语。
但是在汉字中的匹配就有点不一样的。比如:一个中文的公司名称为为:河南海融软件有限公司,使用ik_max_word分词器进行分词候,保存的词条如下:
按照每个tokens中的position的值排序之后就是:河南 南海 融 软件 有限公司 有限 公司,这里的每一个词都相当于英文中的一个单词,所以你输入的查询关键字经过ik_max_word分词候,也必须保持这样的顺序,例如:
- 关键字:河南海融,分词结果:河南 南海 融,所以这个关键字能匹配到。
- 关键字:南海,分词结果:南海,所以也能匹配到。(虽然不是我们想要的)
- 关键字:融软件,分词结果:融 软件,符合上边词条的顺序,也能搜索到。
- 关键字:河南海融有限公司,分词结果:河南 南海 融 有限公司 有限 公司,虽然非常匹配,但是因为这个分词后的词条少了一个软件,那么这个短语就不能和上边的词条匹配,所以也不能搜到。
- 关键字:软件有限,分词结果:软件 有限,不能和上边匹配,搜索不到。
- 关键字:软件有限公司,分词结果,软件 有限公司 有限 公司,能匹配到。
那么问题来了,在上述例子中,第四个关键字:河南海融有限公司 已经非常接近了,很可能是我们粗心,漏掉了一个软件,然后就不能匹配到了,后边的词条 有限公司只要向前移动一个位置就可以匹配到了,如果我们想让这样的关键字也匹配到,那怎么办呢?
刚好还有一个参数叫slop,他的值就是当相隔多远时,我们仍然可以认为匹配得到,这里相当于只相隔了一个单词软件,那么我们可以把slop的值设置为1,那么第4个关键字就可以匹配到了。
不加slop时,匹配不到。
加完slop,匹配到了
Match Phrase Prefix Query:和match_phrase_query差不多,区别就是会将关键字的最后一个词作为前缀来使用查询。
比如查询关键字为:hello w,那么具有hello world,hello work,hello wxxx的词条的数据都会匹配到。我们就可以利用这个功能来做用户查询自动提示相关的查询结果(autocompleted),比如说推荐搜索等。
另外ES可能会匹配所有w开头的单词,这样性能就会很差,我们可以指定只匹配十个w开头的单词就可以了,参数 “max_expansions” : 10,可以来提高我们的搜素性能。
Multi Match Query:多字段的match查询,搜索match的时候可以指定多个字段就不说了。
Common Terms Query:暂时还不理解。
Query String Query:支持复杂lucene query string的语法,对lucene查询语法较为熟悉的人可以使用,一般不推荐。详细请看3.2.2的URL Search就是这种查询。
Simple Query String Query:简化版的Query String Query。
更多详细参数请查看:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/full-text-queries.html
3.3.3 Term Level Query(term级别查询)
这个查询应该是对每个(term)的高级查询,例如前缀查询、范围查询等。term query 相当于全等查询,必须全部匹配。前边说过了,ES会把文本类型分词,分出来的多个结果就叫term。
注意:term是查询时对关键字不分词,上边的全文检索会对搜索的关键字进行分词候再查询。比如搜索 “惠普电脑”,那么只有内容中分词的结果中包含 惠普电脑 的才会被匹配到。
Term Query:精确查找,查找一个字段是否完全匹配所给的关键词,和match query不同的是它不会把查询的关键字进行分词,而是把关键词全部去匹配字段的term,如果匹配到就算查找到。
Terms Query:可以给多个关键词,查找某个字段是否在所给的关键词之中,类似in操作。
Range Query:查询一个是否在一个范围值内。
Exists Query:存在字段查询,判断某个字段是否存在或者是否有值,该查询会排除没有price字段,或者字段值为**null,[ ],[null]的数据,但不会排除为"" 空字串的数据,空字串为有值。
*Prefix Query*:前缀查询,查询字段中是否以给定的关键字为前缀,类似like ‘chi%’ ,这里我们查询是地址中有china的记录。
*Wildcard Query*:通配符查询,用 * 代表一个或者多个字符,用?代表一个或者零个字符,和正则表达式中的通配符差不多。当我们只记得关键词的一部分时,可以用这个查询来,和模糊匹配差不多,估计比那个高级一点。
*Regexp Query*:正则表达式查询,顾名思义,就是查询关键词是正则表达式,如果正则很熟练的话,完全可以只用这一个查询来替代其他查询了,不过据说正则查询性能不是很好,尤其是做模糊匹配的时候。
*Fuzzy Query*:Fuzzy的意思是模糊的,也算是模糊查询的一种吧,但是我更愿意叫它相似度查询,**因为它和传统的模糊查询还不一样。
场景:当我们查找名字Smith时,有些搜索结果就会找出与之相似的Smithe, Smythe, Smyth, Smitt等。这些结果可能只是在关键词上稍作改动之后很相似的结果,或者可以说把这些结果稍作改动之后就和关键词一致了,所以我叫它相似度查询。
关于改动后和关键词一样:这样的改动,我们叫它编辑距离,也就是我们编辑多少次就可以和关键词一致,下边介绍一个新概念:
**Levenshtein Edit Distance: 叫做莱文斯坦编辑距离,是编辑距离的一种。指两个字符串之间,由一个转成另一个所需的最少编辑操作次数。允许的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如:god变成good,只需要增加一个字符o,因此他俩之间的编辑距离为1。下面我还是查询地址中包含china的数据,假设我们忘记china怎么拼了,只记得cha,那么我们设置编辑距离为2,依旧可以查询出来。
Type Query:按文档的类型来查找,这个就不用多说了,当你想查找某个类型的文档时,就用这个吧。
Ids Query:根据id的集合查询,这个我们在sql中就比较常用了,和in操作差不多。
更多详细参数请查看:https://www.elastic.co/guide/en/elasticsearch/reference/6.0/term-level-queries.html
3.3.4 Compound queries(复合查询)
ES的复合查询能包括上述我们介绍过的很多查询,当我们用多条件搜索的时候,我们就要把这好几个查询综合到一起,就形成了复合查询。
Constant Score Query:常量分值查询,用了这个查询,我们就可以强制指定查询结果的分数为多少,一般和filter连用,因为filter忽略分数计算,而你手动指定分数,是很合适的。下面指定boost分数为2.5,返回的结果中_score字段就是2.5。
Bool Query:布尔查询,可以组合多个条件,and、 or、 not等,当组合条件后的结果为true时,就表明是符合条件的记录。查询地址中不包括china但是包括henan的brand字段中开头为ao的记录。
Dis Max Query:默认情况下,当多个field匹配到了少量的关键词 会比少个field匹配到多个关键词排在前面,因为ES计算文档分数的时候会将匹配的语句作为数量做一下平均取一个分数,而不是取其中匹配到多个关键词的分数(这个分数可能最高,但是被根据匹配语句数量一计算平均就低了),我们更期望最高分数的匹配在前边,虽然它被平均计算后低一点,Dis 的意思是Disjunction(分离出,提取出),意思就是提取出最高分的查询。
Function Score Query:这也是一个能够手动改变文档分数的查询,只不过功能比较强大,参数也比较多,暂且就不介绍了。好多改变分数的查询我们在一般情况下是用不到的,等到我们真的要用的时候还要仔细研究,不然的话就可能出现意想不到的结果。
Boosting Query:这也是一个改变分数的查询,它接受一个positive查询和一个negative查询。只有匹配了positive查询的文档才会被包含到结果中,但是同时匹配了negative查询的文档会降低分数,分数被设置为_score和negative_boost参数进行相乘所得到的新结果,negative_boost的值应当小于1.0。
复合查询中,感觉我们常用得还是Bool Query,其他关于修改分数都用的不多,如果有需要的话还是要深入研究一下。
3.3.5 Joining queries
Nested Query:说的内嵌查询,我们先看一个传统的数组查询。比如一个文档user,里边包含一个orders的数组[{orderId:xx,price:xxx,count:xx},{orderId:xx,price:xxx,count:xx}],那么如果当你想查询订单数量等于3的用户,如下:
内嵌查询的数据结构也是嵌套的数组或对象,不同的是内嵌查询会把数组中的每个元素(nested object)作为一个独立隐藏文档单独建索引,因此,我们不能直接查询它们。取而代之,我们必须使用nested查询或者nested filter,使用内嵌查询需要先设置mapping
插入数据:
查询评论中存在 点赞数在400-450之间的且是男用户的 文章,结果如下:
我们再来看一个传统的数组查询用:查询评论中 存在praise为200且为男性评论 的文章,结果却不是我们预期的。
结果中表明,这篇文章的评论中只有一个是男性和一个女性点赞数为200的评论,看起来好像是或者的结果,不符合我们的预期,但是却被查出来了。至于为什么,大家可以看这篇文章:
https://czjxy881.github.io/elasticsearch/%E4%B8%80%E8%B5%B7%E6%9D%A5%E5%AD%A6ES-%E6%B5%85%E8%B0%88Nested%E7%BB%93%E6%9E%84/,这里边说明了详细的原因,这在我们以后的查询中是需要注意的。
**Has Child Query 、 Has Parent Query、Parent Id Query:**这几个查询是用来处理一对多得关系的,类似我们传统数据库中的连接查询,不过要首先建立父子的关系才行。ES低版本是用_parent元字段通过mapping来建立父子关系的,高版本6.0之后使用join类型来建立的,而且父子文档同属于一个类型(不知道为什么,官方文档就这么来,感觉以前挺好的啊,看文档估计是为了提升性能)。
下面建立父子关系,创建一个blogs的索引库,其中类型为_doc,有一个字段叫my_join_field,这个字段的类型为join,join的关系为question是answer的父亲。其中question和answer是join关系中的名称,以后插入数据的时候好表明关系。
插入父文档,name设置为question:
插入子文档,name设置成answer,parent设置父文档的id:
Has Child Query :
Has Parent Query:
Parent Id Query:
3.3.6 Geo queries
就是地理位置的查询,比如我们现在的滴滴,美团定位功能,搜索附近的单车和酒店啥的,都是用到的这个功能,先把酒店的坐标信息存到数据库,然后根据定位的坐标就可以查询你附近的酒店啥的。
地理位置搜索需要数据类型是geo_point的,所以我们要先来创建一个mapping:
下边参考了百度地图上的两个点,添加了两个酒店信息:
**Geo Bounding Box Query:**指定一个矩形区域,查找落在此区域内的酒店(区域点参考上边的百度地图)。
**Geo Distance Query :**距离查询,查询在给定点距离s内的酒店,这就是我们常见的附近的酒店、餐馆啥的搜索功能。(不过感觉es的这个语法有点怪)
Geo Polygon Query:**多边形区域查询和**Geo Bounding Box Query一样,只不过后者是矩形,前者是不规则多边形,貌似没什么用,先不介绍了。
**GeoShape Query:**感觉有点复杂,不想看。
3.3.7 Specialized queries
一些特殊的查询,找了一个比较有用的介绍一下。
**More Like This Query:**相似度查询,可以作为我们常见的推荐、猜你喜欢类似功能的实现。这个还是比较有用的。
[[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xsEcclqA-1627354331291)(D:/360downloads/nut/我的坚果云/815062-20190726115453943-956870259.png)]](file:///D:/360downloads/nut/我的坚果云/815062-20190726115453943-956870259.png)
**min_term_freq:**一篇文档中一个词语至少出现次数,小于这个值的词将被忽略,默认是2
**min_doc_freq:**一个词语最少在多少篇文档中出现,小于这个值的词会将被忽略,默认是5
我这里只有两个文档,所以要设置这两个参数小一点才能查到。
其他还有少量的查询暂时就不做介绍了,感觉没什么用,估计一会有需求再去看吧,中文资料太少了,搜半天也搜不到一个。
四、总结
本文介绍了ES最核心的搜索功能,目的是让我们先上手使用,能满足公司基本业务的搜索,至于其他的个性的配置是什么,集群啊,系统api,日志啊啥以后大家用的更深入的时候可以仔细研究,这篇文章旨在让大家入个门,具体更深入的功能大家自己探索吧,毕竟官方给的功能很多很多,一时半会也介绍不完,有些很可能我们就用不上。最主要的原因还是英文,对我来说就是乱码,既然是乱码了,那就不用看了。
Q.E.D.