摸摸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等,成为排名第一的搜索引擎类应用.
谁在使用∶
- 维基百科,类似百度百科,全文检索,高亮,搜索推荐/2
- The Guardian(国外新闻网站),类似搜狐新闻,用户行为日志(点击,浏览,收藏,评论)+社交网络数据(对某某新闻的相关看法),数据分析,给到每篇新闻文章的作者,让他知道他的文章的公众反馈(好,坏,热门,垃圾,鄙视,崇拜)
- Stack Overflow(国外的程序异常讨论论坛),IT问题,程序的报错,提交上去,有人会跟你讨论和回答,全文检索,搜索相关问题和答案,程序报错了,就会将报错信息粘贴到里面去,搜索有没有对应的答案
- GitHub(开源代码管理),搜索上干亿行代码
- 电商网站,检索商品
- 日志数据分析,logstash采集日志,ES进行复杂的数据分析,ELK技术,elasticsearch+logstash+kibana
- 商品价格监控网站,用户设定某商品的价格阈值,当低于该阈值的时候,发送通知消息给用户,比如说订阅牙膏的监控,如果高露洁牙膏的家庭套装低于50块钱,就通知我,我就去买
- Bl系统,商业智能,Business Intelligence。比如说有个大型商场集团,Bl,分析一下某某区域最近3年的用户消费金额的趋势以及用户群体的组成构成,产出相关的数张报表,**区,最近3年,每年消费金额呈现100%的增长,而且用户群体85%是高级白领,开一个新商场。ES执行数据分析和挖掘,Kibana进行数据可视化
- 国内︰站内搜索(电商,招聘,门户,等等),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请求,向搜索引擎服务器提交一定格式的文件,生成索引;也可以通过提出查找请求,并得到返回结果。
ElasticSearch vs Solr总结
- es基本是开箱即用(解压就可以用),非常简单。Solr安装略微复杂一丢丢!
- Solr利用Zookeeper进行分布式管理,而Elasticsearch自身带有分布式协调管理功能。
- Solr支持更多格式的数据,比如SON、XML、CSV,而Elasticsearch仅支持json文件格式。
- Solr官方提供的功能更多,而Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要kibana友好支撑
- Solr查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;
- ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索。
- Solr是传统搜索应用的有力解决方案,但Elasticsearch更适用于新兴的实时搜索应用。
成本较高。
- Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而Elasticsearch相对开发维护者较少,更新太快,学习使用
ElasticSearch安装
声明: jdk最低要求为jdk1.8.
官网: https://www.elastic.co/cn/elasticsearch/
windows安装
- 解压即可使用
- 熟悉目录
bin 启动文件
config 配置文件
log4j2 日志配置文件
jvm.options java 虚拟机相关的配置
elasticsearch.yml es的配置文件 默认9200端口
lib 相关jar包
modules 功能模块
plugins 插件 (如ik分词)
- 启动,访问9200
服务端口:9200 通信端口:9300
- 访问测试
这里会返回一串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当成一个数据库.(可以建立索引(库), 文档(库中的数据))
建立一个索引(库)
建立一个名为yuankang的索引,5分片,1副本
可以看到刚刚建立的索引
集群健康状态变为黄色是因为我们只有一个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不仅仅适用于日志分析,它还可以支持其它任何数据分析和收集的场景,日志分析和收集只是更具有代表性。并非唯一性。
安装kibana
Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana ,可以通过各种图表进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表板( dashboard )实时显示Elasticsearcb查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch索引监测。
官网:https://www.elastic.co/cn/kibana
启动测试
访问主页http://localhost:5601http://localhost:5601
开发工具
之后的所有操作都在这里
如果想换成中文的,这里有国际化的配置
在config/kibana.yml中设置一下,重启服务,就可以了.
ES核心概念
- 索引
- 字段类型(mapping)
- 文档(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分区)
类型 types
类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,那么elasticsearch是怎么做的呢?
elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型,elasticsearch就开始猜,如果这个值是18,那么
elasticsearch会认为它是整型。但是elasticsearch也可能猜不对,所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用,别整什么幺蛾子。
文档 documents
就是我们的一条条数据
之前说elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,elasticsearch中,文档有几个重要属性:
- 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含key:value
- 可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的! {就是一个json对象}
- 灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。
尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串也可以是整形。因为elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在elasticsearch中,类型有时候也称为映射类型。
filed
每一个document都有对应的一些filed,就像是mysql 表中的一条记录会有多个字段一样.
物理设计: 节点和分片 如何工作?
一个集群至少有一个节点,而一个节点就是一个elasricsearch进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5个分片( primary shard ,又称主分片)构成的,每一个主分片会有一个副本( replica shard ,又称复制分片)
上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。实际上,一个分片是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。
倒排索引
elasticsearch使用的是一种称为倒排索引的结构,采用Lucene倒排索作为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。例如,现在有两个文档,每个文档包含如下内容:
Study every dy, good good up to forever #文档1包含的内容
To forever, study every day, good good up #文档2包含的内容
为了创建倒排索引,我们首先要将每个文档拆分成独立的词(或称为词条或者tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在哪个文档:
term | doc_1 | doc_2 |
---|---|---|
Study | 1 | 0 |
To | 0 | 0 |
every | 1 | 1 |
forever | 1 | 1 |
day | 1 | 1 |
study | 0 | 1 |
good | 1 | 1 |
every | 1 | 1 |
to | 1 | 0 |
up | 1 | 1 |
现在,我们试图搜索to forever,只需要查看包含每个词条的文档 score
term | doc_1 | doc_2 |
---|---|---|
to | 1 | 0 |
forever | 1 | 1 |
total | 2 | 1 |
这样搜出来之后,发现文档1满足的条件更多,因此doc_1的权重会比doc_2更大两个文档都匹配,但是第一个文档比第二个匹配程度更高。如果没有别的条件,现在,这两个包含关键字的文档都将返回。
再来看一个示例,比如我们通过博客标签来搜索博客文章。那么倒排索引列表就是这样的一个结构:
如果要搜索含有python标签的文章,那相对于查找所有原始数据而言,查找倒排索引后的数据将会快的多。只需要查看标签这一栏,然后获取相关的文章ID即可。完全过滤掉无关的所有数据,提高效率!
elasticsearch的索引和Lucene的索引对比
在elasticsearch中,索引这个词被频繁使用,这就是术语的使用。在elasticsearch中,索引被分为多个分片,每份分片是一个Lucene的索引。==所以一个elasticsearch索引是由多个Lucene索引组成的。==别问为什么,谁让elasticsearch使用Lucene作为底层呢!
如无特指,说起索引都是指elasticsearch的索引。
接下来的一切操作都在kibana中Dev Tools下的Console里完成。基础操作!
IK分词器插件
什么是IK分词器
分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如“我爱中国”会被分为“我"“爱”“中”"国”,这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。
IK提供了两个分词算法:ik_smart
和ik_max_word
,其中 ik_smart
为最少切分, ik_max_word
为最细粒度划分!一会我们测试!
如果要使用中文,建议使用ik分词器,好像elasticsearch官网还有SmartCN分词器,但我没用过…
安装
- https://github.com/medcl/elasticsearch-analysis-ik 下载latest的release版本就好
- 下载完毕后,放到elasticsearch的plugins目录下就行了,注意: 需要解压
- 重启观察ES,可以看到ik分词器被加载了
- 可以通过
elasticsearch-plugin
这个命令查看所有被加载的插件 - 使用kibana进行测试
最少分词:ik_smart
最大努力分词: ik_max_word
尽最大努力分词,那这些词又是怎么拆的呢?肯定有个字典
但是某些情况下,拆开的词并不是我们想要的,这个时候就需要把这种自己需要的词加到分词器的字典中
ik分词器增加自己的配置
在ik的config目录下
新增一个字典yuankang.dic,内容写上我们自己的词
修改其默认配置
重启es
我们惊喜的发现 刘亦菲
没有再被拆开了,分词生效了
REST风格说明
method | url地址 | 描述 |
---|---|---|
PUT | localhost:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST | localhost:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST | localhost:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE | localhost:9200/索引名称/类型名称/文档id | 删除文档 |
GET | localhost:9200/索引名称/类型名称/文档 id | 通过文档id查询文档 |
POST | localhost: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"
}
}
}
}
通过GET请求,可以看到我们刚刚设定的字段属性
如果自己的文档字段没有指定,那么es就会给我们默认设置配置字段类型.
扩展: 通过命令查看es的索引情况 通过GET _cat/可以获取es当前的很多信息
获取集群健康状态 GET _cat/health
(后面加上?v
就是显示字段名称)
获取索引状态信息 GET _cat/indices?v
修改 提交还是使用put即可.
但是如果使用put进行更新,如果你修改后的字段因为疏忽而漏了一个字段,那么新的版本中就没有这个字段了,所以建议使用新的方式更新
使用POST进行更新
POST /test1/_doc/1/_update
{
"doc":{
"name":"张三"
}
}
可以看到已经更新成功了,不过注意到上面的红色提示,说type已经删除了,建议用新的命令.
前面我们也提到过嘛,7.x里面实际上已经不用type了,所以直接用documentID就ok了.
POST /test1/_update/1
{
"doc": {
"age":22
}
}
可以看到返回值一样更新成功,并且没有警告信息了
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": "花玲"
}
}
}
结果过滤 _source
相当于数据库的select *
,改成select name,age
GET /test2/_search
{
"query": {
"match": {
"name": "花玲"
}
},
"_source": ["name","age"] #注意,_source是结果过滤,与query是平级
}
与query同级别,属于"结果过滤"
排序 sort
GET /test2/_search
{
"query": {
"match": {
"name": "花玲"
}
},
"sort": [
{
"age": {
"order": "desc" #按照年龄降序排序
}
}
]
}
由于有了sort排序,原来的score就没了
与query同级别,属于"结果过滤"
分页 from size
GET /test2/_search
{
"query": {
"match": {
"name": "花玲"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
],
"from": 0, #从哪里开始,offset,懂?
"size": 1 #每页的数量,limit,懂?
}
与query同级别,属于"结果过滤"
布尔值查询 bool
must
must 都要匹配 相当于mysql中的and, where name = ‘大大呱’ and age = 18
GET /test2/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "大大呱"
}
},
{
"match": {
"age": 18
}
}
]
}
}
}
使用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
}
}
]
}
}
}
以上结果很清晰就可以看出来了
must_not
不等于 != 用must_not
相当于where name != ‘大大呱’ and age!=20
GET /test2/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"name": "大大呱"
}
},
{
"match": {
"age": 20
}
}
]
}
}
}
filter
过滤,可以写范围相关的了
这里相当于where name = ‘花玲’ and age > 19
GET /test2/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "花玲"
}
}
],
"filter": [
{
"range": {
"age": {
"gt": 19 # 年龄大于19的
}
}
}
]
}
}
}
-
gt 大于
-
lt 小于
-
gte 大于等于 (e的意思是equals)
-
lte 小于等于
匹配多个条件
#搜索名字中带有 花 或 哈 的document
GET /test2/_search
{
"query": {
"match": {
"name": "花 哈" #条件之间使用空格隔开
}
}
}
注意:此时必须是要经过分词的条件才可以搜寻.就比如说我们明明是有"大大呱"这一条document的
但是使用匹配的时候直接搜索"大"却找不到记录
原因是因为我们在建立index的时候,给name字段设置的分词是ik_smart
.而ik_smart
把大大呱给拆成了"大大"和"呱",所以我们以"大"为搜索条件时找不到
精确查询
term 查询是直接通过倒排索引指定的词条进程精确查找的.
两种查询条件
- term 直接通过倒排索引精确查找
- match 会使用分词器解析, 先分析文档, 然后通过分析的文档进行查询
两种字段的类型
- text 会被分词器分词
- keyword 作为一个整体,不会被分词器分词
这个应该很好理解,keyword意义就是"非常重要的,明了的,浑然一体的"那种感觉
text就没啥其他意义,就是一个"文本"
这里就不演示了.
GET /test2/_search
{
"query": {
"term": {
"name": "花"
}
}
}
可以找到
试试下面这个
GET /test2/_search
{
"query": {
"term": { #term
"name": "花玲"
}
}
}
居然就找不到了
GET /test2/_search
{
"query": {
"match": { #match
"name": "花玲"
}
}
}
但是我们用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":{}
}
}
}
<em> </em> 这是es默认的高亮标签,我们自已自定义高亮的样式
自定义高亮样式
GET test2/_search
{
"query": {
"match": {
"name": "花玲"
}
},
"highlight": {
"pre_tags": "<p class='key' style='color:red'>", #前缀
"post_tags": "</p>", #后缀
"fields": {
"name":{} #要高亮的字段
}
}
}
基本的东西就到此为止啦, 下一篇计划中的是java与golang的es客户端API操作.
感谢你的view,如有问题欢迎指正.