ElasticSearch-美丽优雅

摸摸ElasticSearch

ES的背景,为什么要了解ES?

搜索引擎

我们平时与mysql打交道,使用最多的模糊搜索是like %xxx%,但是如果数据量非常大,那么这个操作实际上是非常消耗性能的,我们平时可能会去添加一些索引,但是数据量大了之后其实也起不到什么作用,特别是像like这种,本来就没办法走索引.

这个时候我们非常迫切的需要一款高质量的,高性能的,最好是能多线程跑的专门用于搜索的组件来提升我们搜索的效率. 这个时候,ElasticSearch出现了.

Lucene

Lucene是一套信息检索工具包, jar包, 不包含搜索引擎系统

包含的: 索引结构,读写索引的工具,排序,搜索规则…是个工具类

Lucene和ES的关系

ElasticeSearch是基于Lucene做了一些封装和增强.

ElasticSearch概述

Elasticsearch,简称为es,es是一个开源的高扩展分布式全文检索引擎,它可以近乎实时的存储、检索数据,本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
据国际权威的数据库产品评测机构DBEngines的统计,在2016年1月,ElasticSearch已超过Solr等,成为排名第一的搜索引擎类应用.

谁在使用∶

  1. 维基百科,类似百度百科,全文检索,高亮,搜索推荐/2
  2. The Guardian(国外新闻网站),类似搜狐新闻,用户行为日志(点击,浏览,收藏,评论)+社交网络数据(对某某新闻的相关看法),数据分析,给到每篇新闻文章的作者,让他知道他的文章的公众反馈(好,坏,热门,垃圾,鄙视,崇拜)
  3. Stack Overflow(国外的程序异常讨论论坛),IT问题,程序的报错,提交上去,有人会跟你讨论和回答,全文检索,搜索相关问题和答案,程序报错了,就会将报错信息粘贴到里面去,搜索有没有对应的答案
  4. GitHub(开源代码管理),搜索上干亿行代码
  5. 电商网站,检索商品
  6. 日志数据分析,logstash采集日志,ES进行复杂的数据分析,ELK技术,elasticsearch+logstash+kibana
  7. 商品价格监控网站,用户设定某商品的价格阈值,当低于该阈值的时候,发送通知消息给用户,比如说订阅牙膏的监控,如果高露洁牙膏的家庭套装低于50块钱,就通知我,我就去买
  8. Bl系统,商业智能,Business Intelligence。比如说有个大型商场集团,Bl,分析一下某某区域最近3年的用户消费金额的趋势以及用户群体的组成构成,产出相关的数张报表,**区,最近3年,每年消费金额呈现100%的增长,而且用户群体85%是高级白领,开一个新商场。ES执行数据分析和挖掘,Kibana进行数据可视化
  9. 国内︰站内搜索(电商,招聘,门户,等等),IT系统搜索(OA,CRM,ERP,等等),数据分析(ES热门的一个使用场景)

ElasticSearch与Solr的差别

Solr简介

Solr是Apache下的一个顶级开源项目,采用ava开发,它是基于Lucene的全文搜索服务器。Solrd提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化
Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Solr索引的实现方法很简单,用POST方法向Solr服务器发送一个描述Field及其内容的XML文档,Solr根据xml文档添加、删除、更新索引。Solr搜索只需要发送HTTPGET请求,然后对Solr返回xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。
solr是基于lucene开发企业级搜索服务器,实际上就是封装了lucene。提交一定格式的文件,生成索引;也可以通过提出查找请求,并得到返回结果。
Solr是一个独立的企业级搜索应用服务器,它对外提供类似于
Web-service的API接口
。用户可以通过http请求,向搜索引擎服务器提交一定格式的文件,生成索引;也可以通过提出查找请求,并得到返回结果。

image-20200912155905430

image-20200912155939027

image-20200912155958017

image-20200912160022201

ElasticSearch vs Solr总结

  1. es基本是开箱即用(解压就可以用),非常简单。Solr安装略微复杂一丢丢!
  2. Solr利用Zookeeper进行分布式管理,而Elasticsearch自身带有分布式协调管理功能。
  3. Solr支持更多格式的数据,比如SON、XML、CSV,而Elasticsearch仅支持json文件格式。
  4. Solr官方提供的功能更多,而Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑
  5. Solr查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;
    • ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索。
    • Solr是传统搜索应用的有力解决方案,但Elasticsearch更适用于新兴的实时搜索应用。
      成本较高。
  6. Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而Elasticsearch相对开发维护者较少,更新太快,学习使用

ElasticSearch安装

声明: jdk最低要求为jdk1.8.

官网: https://www.elastic.co/cn/elasticsearch/

image-20200912161133493

windows安装

  1. 解压即可使用
  2. 熟悉目录

image-20200912162859097

bin		启动文件
config 	配置文件
	log4j2 				日志配置文件
	jvm.options java 	虚拟机相关的配置
	elasticsearch.yml 	es的配置文件 默认9200端口 
lib 	相关jar包
modules 功能模块
plugins 插件 (如ik分词)
  1. 启动,访问9200

image-20200912163834072

服务端口:9200 通信端口:9300

  1. 访问测试

image-20200912164045429

这里会返回一串json, es非常经典的一句话==“You Know, for Search”==

(可能你们看到的界面不一样,因为我装了浏览器json解析插件)

安装可视化界面 es head 插件

  • git clone git://github.com/mobz/elasticsearch-head.git

  • cd elasticsearch-head

  • npm install

  • npm run start

  • open http://localhost:9100/

在elasticsearch.yml中配置跨域

http.cors.enabled: true
http.cors.allow-origin: "*"

不过我更喜欢crebro,我觉得好看一点 https://github.com/lmenezes/cerebro

先把es当成一个数据库.(可以建立索引(库), 文档(库中的数据))

建立一个索引(库)

image-20200912172407985

建立一个名为yuankang的索引,5分片,1副本

image-20200912172508694

可以看到刚刚建立的索引

image-20200912172532323

集群健康状态变为黄色是因为我们只有一个node,无法创建副本

不过这些东西我觉得还是用kibana比较好.先略过吧,cerebro用来看集群状态就行了

了解ELK

ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称。市面上也被成为Elastic Stack。其中Elasticsearch是一个基于Lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。像类似百度、谷歌这种大数据全文搜索引擎的场景都可以使用Elasticsearch作为底层支持框架,可见Elasticsearch提供的搜索能力确实强大,市面上很多时候我们简称Elasticsearch为es。
Logstash是ELK的中央数据流引擎,用于从不同目标(文件/数据存储/MQ)收集的不同格式数据,经过过滤后支持输出到不同目的地(文件/MQ/redis/elasticsearch/kafka等 )。Kibana可以将elasticsearch的数据通过友好的页面展示出来,提供实时分析的功能。

市面上很多开发只要提到ELK能够一致说出它是一个日志分析架构技术栈总称,但实际上ELK不仅仅适用于日志分析,它还可以支持其它任何数据分析和收集的场景,日志分析和收集只是更具有代表性。并非唯一性。

image-20200912181701788

安装kibana

Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana ,可以通过各种图表进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板( dashboard )实时显示Elasticsearcb查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch索引监测。

官网:https://www.elastic.co/cn/kibana

启动测试

image-20200912190736505

访问主页http://localhost:5601http://localhost:5601

image-20200912190747237

开发工具

image-20200912191127606

之后的所有操作都在这里

如果想换成中文的,这里有国际化的配置

image-20200912191443407

在config/kibana.yml中设置一下,重启服务,就可以了.

image-20200912191550165

ES核心概念

  1. 索引
  2. 字段类型(mapping)
  3. 文档(document)

概述

在前面的学 习中,我们已经掌握了es是什么,同时也把es的服务已经安装启动,那么es是如何去存储数据,数据结构是什么,又是如何实现搜索的呢?

集群,节点,索引,类型,文档,分片,映射是什么?

ElasticSearch是面向文档,以下是关系型数据库和es的对比

关系型数据库ElasticSearch
数据库(database)索引(indices)
表(tables)类型(types)
行(rows)文档(documents)
字段(columns)字段(fields)

es(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列0)

物理设计

elasticsearch在后台把每个索引划分成多个分片,每分分片可以在集群中的不同服务器间迁移

默认就是以集群方式存在.只有一个节点也是一个集群(一个人就是一支军队?)

默认的集群名称就是elasticsearch

逻辑设计

一个索引类型中,包含多个文档,比如说文档1,文档2.当我们在索引一篇文档时,可以通过这样的一个规则找到它:

索引 -> 类型 -> 文档ID

通过这个组合我们就能索引到某个具体的文档.注意: ID不必是整数,实际上他是个字符串

索引

就是数据库

  • 索引时映射类型的容器,es中的索引是一个非常大的文档集合.

  • 索引存储了映射类型的字段和其他设置.然后他们被存储到各个分片上.

  • es默认每个索引5个分片,每个分片都会存在至少一个备份分片,(参考kafka分区)

image-20200912205119442

类型 types

类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,那么elasticsearch是怎么做的呢?
elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型,elasticsearch就开始猜,如果这个值是18,那么
elasticsearch会认为它是整型。但是elasticsearch也可能猜不对,所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用,别整什么幺蛾子。

image-20200912210433158

文档 documents

就是我们的一条条数据

之前说elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,elasticsearch中,文档有几个重要属性:

  • 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含key:value
  • 可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的! {就是一个json对象}
  • 灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。

尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串也可以是整形。因为elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在elasticsearch中,类型有时候也称为映射类型。

image-20200912210512093

filed

每一个document都有对应的一些filed,就像是mysql 表中的一条记录会有多个字段一样.

image-20200912210550293

物理设计: 节点和分片 如何工作?

一个集群至少有一个节点,而一个节点就是一个elasricsearch进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5个分片( primary shard ,又称主分片)构成的,每一个主分片会有一个副本( replica shard ,又称复制分片)

image-20200912210829732

上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。实际上,一个分片是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。

倒排索引

elasticsearch使用的是一种称为倒排索引的结构,采用Lucene倒排索作为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。例如,现在有两个文档,每个文档包含如下内容:

Study every dy, good good up to forever  #文档1包含的内容
To forever, study every day, good good up #文档2包含的内容

为了创建倒排索引,我们首先要将每个文档拆分成独立的词(或称为词条或者tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在哪个文档:

termdoc_1doc_2
Study10
To00
every11
forever11
day11
study01
good11
every11
to10
up11

现在,我们试图搜索to forever,只需要查看包含每个词条的文档 score

termdoc_1doc_2
to10
forever11
total21

这样搜出来之后,发现文档1满足的条件更多,因此doc_1的权重会比doc_2更大两个文档都匹配,但是第一个文档比第二个匹配程度更高。如果没有别的条件,现在,这两个包含关键字的文档都将返回。
再来看一个示例,比如我们通过博客标签来搜索博客文章。那么倒排索引列表就是这样的一个结构:

image-20200912212621183

如果要搜索含有python标签的文章,那相对于查找所有原始数据而言,查找倒排索引后的数据将会快的多。只需要查看标签这一栏,然后获取相关的文章ID即可。完全过滤掉无关的所有数据,提高效率!

elasticsearch的索引和Lucene的索引对比

在elasticsearch中,索引这个词被频繁使用,这就是术语的使用。在elasticsearch中,索引被分为多个分片,每份分片是一个Lucene的索引。==所以一个elasticsearch索引是由多个Lucene索引组成的。==别问为什么,谁让elasticsearch使用Lucene作为底层呢!
如无特指,说起索引都是指elasticsearch的索引。

接下来的一切操作都在kibana中Dev Tools下的Console里完成。基础操作!

IK分词器插件

什么是IK分词器

分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如“我爱中国”会被分为“我"“爱”“中”"国”,这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。
IK提供了两个分词算法:ik_smartik_max_word,其中 ik_smart为最少切分, ik_max_word为最细粒度划分!一会我们测试!

如果要使用中文,建议使用ik分词器,好像elasticsearch官网还有SmartCN分词器,但我没用过…

安装

  1. https://github.com/medcl/elasticsearch-analysis-ik 下载latest的release版本就好
  2. 下载完毕后,放到elasticsearch的plugins目录下就行了,注意: 需要解压

image-20200913105128295

  1. 重启观察ES,可以看到ik分词器被加载了

image-20200913105249459

  1. 可以通过elasticsearch-plugin这个命令查看所有被加载的插件
  2. 使用kibana进行测试

最少分词:ik_smart

image-20200913105900596

最大努力分词: ik_max_word

image-20200913105956440

尽最大努力分词,那这些词又是怎么拆的呢?肯定有个字典

但是某些情况下,拆开的词并不是我们想要的,这个时候就需要把这种自己需要的词加到分词器的字典中

image-20200913110940055

ik分词器增加自己的配置

在ik的config目录下

image-20200913110536287

新增一个字典yuankang.dic,内容写上我们自己的词

image-20200913111115573

修改其默认配置

image-20200913111219023

重启es

我们惊喜的发现 刘亦菲没有再被拆开了,分词生效了

image-20200913111513089

REST风格说明

methodurl地址描述
PUTlocalhost:9200/索引名称/类型名称/文档id创建文档(指定文档id)
POSTlocalhost:9200/索引名称/类型名称创建文档(随机文档id)
POSTlocalhost:9200/索引名称/类型名称/文档id/_update修改文档
DELETElocalhost:9200/索引名称/类型名称/文档id删除文档
GETlocalhost:9200/索引名称/类型名称/文档 id通过文档id查询文档
POSTlocalhost:9200/索引名称/类型名称/_search查询所有数据

基础测试

创建一个索引

PUT /test1/type1/1
{
  "name":"yuankang",
  "age":18
}

这里我们创建了一个名为test1的索引, 类型名为type1,当然, 在es7.x中, 有没有这个type实际上都是无所谓的.最后的1是文档id,相当于数据库表中的一条记录的id

类型

其实我们可以注意到,在上面的操作中,我们实际上是没有对各个字段进行赋值的,如果没有赋值,es就会去猜,有时候结果并不是我们想要的.大概有以下几种类型可以在创建的时候就指定.

  • 字符串类型
    text, keyword(不可分词)
  • 数值类型
    long, integer, short, byte, double, float, half float,scaled float
  • 日期类型
    date
  • te布尔值类型
    boolean
  • 二进制类型
    binary
  • ·等等……

指定字段的类型

PUT /test2
{
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "age":{
        "type": "long"
      },
      "birth":{
        "type": "date"
      }
    }
  }
}

image-20200913123909125

通过GET请求,可以看到我们刚刚设定的字段属性

如果自己的文档字段没有指定,那么es就会给我们默认设置配置字段类型.

扩展: 通过命令查看es的索引情况 通过GET _cat/可以获取es当前的很多信息

获取集群健康状态 GET _cat/health (后面加上?v就是显示字段名称)

获取索引状态信息 GET _cat/indices?v

修改 提交还是使用put即可.

但是如果使用put进行更新,如果你修改后的字段因为疏忽而漏了一个字段,那么新的版本中就没有这个字段了,所以建议使用新的方式更新

使用POST进行更新

POST /test1/_doc/1/_update
{
  "doc":{
    "name":"张三"
  }
}

image-20200913132337721

可以看到已经更新成功了,不过注意到上面的红色提示,说type已经删除了,建议用新的命令.

前面我们也提到过嘛,7.x里面实际上已经不用type了,所以直接用documentID就ok了.

POST /test1/_update/1
{
  "doc": {
    "age":22
  }
}

可以看到返回值一样更新成功,并且没有警告信息了

image-20200913132616956

GET /test1/_doc/1 #命令

#返回值,可以看到刚刚的两次修改都ok了,version变成了3
{
  "_index" : "test1",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "张三",
    "age" : 22
  }
}

删除索引

DELETE /test1

这个没啥好说的

关于文档的基本操作

基本操作

增删改上面都有提到,这里不再赘述

# 增加一个index,为index设置各个字段 (相当于给数据库表设置字段类型,其实index相当于数据库,但是7.x之后取消了type,默认就是_doc,所以就相当于表了)
PUT /user
{
    "mapping":{
        "properties":{
            "name":{
                "type":"keyword"
            },
            "age":{
                "type":"integer"
            }
        }
    }
}

# 增加一条document
PUT /user/_doc/1
{
    "name":"刘亦菲",
    "age":18
}

# 增加一条document 随机id
POST /test2/_doc
{
  "name":"花玲",
  "age":18,
  "birth":"2020-01-01"
}

改(更新)

#[不推荐]第一种方式,使用PUT进行更新,但是有可能稍微不注意把字段给清空了.
PUT /user/_doc/1
{
    "age":20	#这里我们并没有加上name字段,所以在es里,这一条document的name就被覆盖了(清空)
}

#[推荐]第二种方式,使用POST进行更新,更加灵活

POST /user/1/_update
{
    "age":20 	#只修改age字段,原来的name字段并不会被清空.
}

DELETE /user/_doc/1 	#删除id为1的这个document
DELETE /user/			#删除整个index (删库跑路)

查(简单)

GET /user/_doc/1		#获取id为1的document

#带条件的查询
GET /test2/_search?q=name:花玲
#结果
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "test2",
        "_type" : "_doc",
        "_id" : "N1aHhnQBRfC4IpwAc7q7",
        "_score" : 0.2876821,	#可以看到这里的score,如果有多条查询出来的结果,匹配度越高分值越高
        "_source" : {
          "name" : "花玲",
          "age" : 18,
          "birth" : "2020-01-01"
        }
      }
    ]
  }
}

复杂操作

条件查询 query match
GET /test2/_search
{
  "query": {
    "match": {
      "name": "花玲"
    }
  }
}

image-20200913164630762

结果过滤 _source

相当于数据库的select *,改成select name,age

GET /test2/_search
{
  "query": {
    "match": {
      "name": "花玲"
    }
  },
  "_source": ["name","age"]	#注意,_source是结果过滤,与query是平级
}

image-20200913170153232

与query同级别,属于"结果过滤"

排序 sort
GET /test2/_search
{
  "query": {
    "match": {
      "name": "花玲"
    }
  },
  "sort": [
    {
      "age": {
        "order": "desc"	#按照年龄降序排序
      }
    }
  ]
}

image-20200913170823685

由于有了sort排序,原来的score就没了

与query同级别,属于"结果过滤"

分页 from size
GET /test2/_search
{
  "query": {
    "match": {
      "name": "花玲"
    }
  },
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ],
  "from": 0,	#从哪里开始,offset,?
  "size": 1		#每页的数量,limit,?
}

image-20200913171903471

与query同级别,属于"结果过滤"

布尔值查询 bool
must

must 都要匹配 相当于mysql中的and, where name = ‘大大呱’ and age = 18

GET /test2/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "大大呱"
          }
        },
        {
          "match": {
            "age": 18
          }
        }
      ]
    }
  }
}

image-20200913172801011

使用bool就可以用多条件精确查询,如果不使用bool的话,就只能使用一个match,使用bool可以使用多个match进行联合查询

should

那有没有or呢? 有的, should就ok

should相当于 where name = ‘大大呱’ or age = 20

GET /test2/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "name": "大大呱"
          }
        },
        {
          "match": {
            "age": 20
          }
        }
      ]
    }
  }
}

image-20200913184431792

以上结果很清晰就可以看出来了

must_not

不等于 != 用must_not

相当于where name != ‘大大呱’ and age!=20

GET /test2/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "match": {
            "name": "大大呱"
          }
        },
        {
          "match": {
            "age": 20
          }
        }
      ]
    }
  }
}

image-20200913184652676

filter

过滤,可以写范围相关的了

这里相当于where name = ‘花玲’ and age > 19

GET /test2/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "花玲"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "age": {
              "gt": 19	# 年龄大于19}
          }
        }
      ]
    }
  }
}

image-20200913185213244

  • gt 大于

  • lt 小于

  • gte 大于等于 (e的意思是equals)

  • lte 小于等于

匹配多个条件
#搜索名字中带有 花 或 哈 的document
GET /test2/_search
{
 "query": {
   "match": {
     "name": "花 哈"  #条件之间使用空格隔开
   }
 }
}

image-20200913190007366

注意:此时必须是要经过分词的条件才可以搜寻.就比如说我们明明是有"大大呱"这一条document的

但是使用匹配的时候直接搜索"大"却找不到记录

原因是因为我们在建立index的时候,给name字段设置的分词是ik_smart.而ik_smart把大大呱给拆成了"大大"和"呱",所以我们以"大"为搜索条件时找不到

image-20200913190508247

精确查询

term 查询是直接通过倒排索引指定的词条进程精确查找的.

两种查询条件

  • term 直接通过倒排索引精确查找
  • match 会使用分词器解析, 先分析文档, 然后通过分析的文档进行查询

两种字段的类型

  • text 会被分词器分词
  • keyword 作为一个整体,不会被分词器分词

这个应该很好理解,keyword意义就是"非常重要的,明了的,浑然一体的"那种感觉

text就没啥其他意义,就是一个"文本"

这里就不演示了.

GET /test2/_search
{
  "query": {
    "term": {
      "name": "花"
    }
  }
}

可以找到

image-20200913192548443

试试下面这个

GET /test2/_search
{
  "query": {
    "term": {		#term
      "name": "花玲"
    }
  }
}

image-20200913192644910

居然就找不到了

GET /test2/_search
{
  "query": {
    "match": {			#match
      "name": "花玲"
    }
  }
}

image-20200913192724144

但是我们用match又可以找到

原因?

还是我们上面说的,term是直接去倒排索引里面捞,捞到了就展现出来

如果倒排索引里没有,那就捞不到,又由于我们的分词器把"花玲"给拆成了"花"和"玲"

所以倒排索引里是没有"花玲"这个索引的. 于是term就查不到

match能找到是因为match会先对条件进行分词,再去倒排索引中捞,所以是能找到的.

精确查询多个值
GET test2/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "name": "花"
          }
        },
        {
          "term": {
            "name": "呱"
          }
        }
      ]
    }
  }
}

不管是match还是term,反正你要用多个条件联合查询(主要是and和or,还有范围搜寻)的话就要在bool下面搞,懂?

哦对了,还有多条件查询的时候,快捷一点直接使用match条件就行了,match里面的条件用空格隔开

(让我想起了我们的大数据共享平台…那个糟心的搜索,肯定就是直接用match中写多条件做的,导致我们搜索一长串字符串的时候,反而找不到,因为分词没分对…用关键词+空格精确率就上去了…)

高亮查询

注意,highlight与query是同级别,属于"结果过滤",或者说在这里属于"结果操作"

GET test2/_search
{
  "query": {
    "match": {
      "name": "花玲"
    }
  },
  "highlight": {
    "fields": {
      "name":{}
    }
  }
}

image-20200913200809238

<em> </em> 这是es默认的高亮标签,我们自已自定义高亮的样式

自定义高亮样式

GET test2/_search
{
  "query": {
    "match": {
      "name": "花玲"
    }
  },
  "highlight": {
    "pre_tags": "<p class='key' style='color:red'>", 	#前缀
    "post_tags": "</p>", 	#后缀
    "fields": {
      "name":{}		#要高亮的字段
    }
  }
}

image-20200913201232255

基本的东西就到此为止啦, 下一篇计划中的是java与golang的es客户端API操作.

感谢你的view,如有问题欢迎指正.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值