1、ElasticSearch简介
1.1、ElasticSearch(简称ES)
- Elasticsearch是用Java开发并且是当前最流行的开源的企业级搜索引擎。能够达到近实时搜索,稳定,可靠,快速,安装使用方便。
- 客户端支持Java、.NET(C#)、PHP、Python、Ruby等多种语言。
官方网站: https://www.elastic.co/
下载地址: https://www.elastic.co/cn/start
1.2、应用场景
- 网站搜索、垂直搜索、代码搜索;
- 日志管理与分析、安全指标监控、应用性能监控、Web抓取舆情分析;
1.3、主要功能
- 海量数据的分布式存储以及集群管理,达到了服务与数据的高可用以及水平扩展;
- 近实时搜索,性能卓越。对结构化、全文、地理位置等类型数据的处理;
- 海量数据的近实时分析(聚合功能)
1.4、ElasticSearch与Lucene的关系
Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库(框架),但是想要使用Lucene,必须使用Java来作为开发语言并将其直接集成到你的应用中,并且Lucene的配置及使用非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
Lucene缺点:
- 只能在Java项目中使用,并且要以jar包的方式直接集成项目中
- 使用非常复杂-创建索引和搜索索引代码繁杂
- 不支持集群环境-索引数据不同步(不支持大型项目)
- 索引数据如果太多就不行,索引库和应用所在同一个服务器,共同占用硬盘共用空间少
1.5、ES vs Solr比较
ES vs Solr 检索速度
当单纯的对已有数据进行搜索时,Solr更快。
当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。
大型互联网公司,实际生产环境测试,将搜索引擎从Solr转到 Elasticsearch以后的平均查询速度有了50倍的提升。
总结:
二者安装都很简单。
- Solr 利用 Zookeeper 进行分布式管理,而Elasticsearch 自身带有分布式协调管理功能。
- Solr 支持更多格式的数据,比如JSON、XML、CSV,而 Elasticsearch 仅支持json文件格式。
- Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。
- Solr 是传统搜索应用的有力解决方案,但 Elasticsearch更适用于新兴的实时搜索应用。
1.6、ES vs 关系型数据库
2、Lucene全文检索框架
2.1、什么是全文检索
- 通过一个程序扫描文本中的每一个单词,针对单词建立索引,并保存该单词在文本中的位置、以及出现的次数
- 用户查询时,通过之前建立好的索引来查询,将索引中单词对应的文本位置、出现的次数返回给用户,因为有了具体文本的位置,所以就可以将具体内容读取出来了
2.2、分词原理之倒排索引
倒排索引总结:
索引就类似于目录,平时我们使用的都是索引,都是通过主键定位到某条数据,那么倒排索引呢,刚好相反,数据对应到主键.这里以一个博客文章的内容为例:
1.索引:
2.倒排索引
假如,我们有一个站内搜索的功能,通过某个关键词来搜索相关的文章,那么这个关键词可能出现在标题中,也可能出现在文章内容中,那我们将会在创建或修改文章的时候,建立一个关键词与文章的对应关系表,这种,我们可以称之为倒排索引,因此倒排索引,也可称之为反向索引.如:
3、Elasticsearch中的核心概念
3.1、索引 index
- 一个索引就是一个拥有几分相似特征的文档的集合。比如说,可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引
- 一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字
3.2、映射 mapping
- ElasticSearch中的映射(Mapping)用来定义一个文档
- mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分词器、是否被索引等等,这些都是映射里面可以设置的
3.3、字段 Field
- 相当于是数据表的字段|列
3.4、字段类型 Type
- 每一个字段都应该有一个对应的类型,例如:Text、Keyword、Byte等
3.5、文档 document
- 一个文档是一个可被索引的基础信息单元,类似一条记录。文档以JSON(Javascript ObjectNotation)格式来表示;
3.6、集群 cluster
- 一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能
3.7、节点 node
- 一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能
- 一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中
- 这意味着,如果在网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中
- 在一个集群里,可以拥有任意多个节点。而且,如果当前网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。
3.8、分片和副本 shards&replicas - 分片
- 一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢
- 为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片
- 当创建一个索引的时候,可以指定你想要的分片的数量
- 每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上
- 分片很重要,主要有两方面的原因:
1、允许水平分割/扩展你的内容容量
2、允许在分片之上进行分布式的、并行的操作,进而提高性能/吞吐量 - 至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户来说,这些都是透明的
3.9、分片和副本 shards&replicas - 副本
- 在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做副本分片,或者直接叫副本
- 副本之所以重要,有两个主要原因
1、在分片/节点失败的情况下,提供了高可用性:注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的
2、扩展搜索量/吞吐量,因为搜索可以在所有的副本上并行运行:每个索引可以被分成多个分片。一个索引有0个或者多个副本一旦设置了副本,每个索引就有了主分片和副本分片,分片和副本的数量可以在索引创建的时候指定在索引创建之后,可以在任何时候动态地改变副本的数量,但是不能改变分片的数量
4、安装ElasticSearch
4.1、创建普通用户
- ES不能使用root用户来启动,必须使用普通用户来安装启动。
4.2、修改配置文件
修改elasticsearch.yml (使用es安装的用户)
mkdir ‐p /usr/local/es/elasticsearch‐7.6.1/log
mkdir ‐p /usr/local/es/elasticsearch‐7.6.1/data
cd /usr/local/es/elasticsearch‐7.6.1/config
vim elasticsearch.yml
cluster.name: my‐application
node.name: node‐1
path.data: /usr/local/es/elasticsearch‐7.6.1/data
path.logs: /usr/local/es/elasticsearch‐7.6.1/log
network.host: 0.0.0.0
http.port: 9200
discovery.seed_hosts: ["服务器IP"]
cluster.initial_master_nodes: ["node‐1"]
bootstrap.system_call_filter: false
bootstrap.memory_lock: false
http.cors.enabled: true
http.cors.allow‐origin: "*"
4.3、修改jvm.option
修改jvm.option配置文件,调整jvm堆内存大小
cd /usr/local/es/elasticsearch‐7.6.1/config
vi jvm.options
‐Xms2g
‐Xmx2g
4.4、修改系统配置,解决启动时候的问题
由于现在使用普通用户来安装es服务,且es服务对服务器的资源要求比较多,包括内存大小,线程数等。所以我们需要给普通用户解开资源的束缚
普通用户打开文件的最大数限制
ES因为需要大量的创建索引文件,需要大量的打开系统的文件,所以我们需要解除linux系统当中打开文件最大数目的限制,不然ES启动就会抛错
sudo vi /etc/security/limits.conf
* soft nofile 65536
* hard nofile 131072
* soft nproc 4096
* hard nproc 4096
普通用户启动线程数限制
max number of threads [1024] for user [es] likely too low, increase to
at least [4096]原因:无法创建本地线程问题,用户最大可创建线程数太小
解决方案:修改90-nproc.conf 配置文件。
Centos6
sudo vi /etc/security/limits.d/90‐nproc.conf
Centos7
sudo vi /etc/security/limits.d/20‐nproc.conf
* soft nproc 1024#修改为
* soft nproc 4096
普通用户调大虚拟内存
max virtual memory areas vm.max_map_count [65530] likely too low,increase to at least [262144]
调大系统的虚拟内存
原因:最大虚拟内存太小
vi /etc/sysctl.conf,追加以下内容:
vm.max_map_count=655360
保存后,执行:sysctl ‐p
5、安装IK分词器
我们后续也需要使用Elasticsearch来进行中文分词,所以需要单独给Elasticsearch安装IK分词器插件。以下为具体安装步骤:
5.1.1、下载Elasticsearch IK分词器
https://github.com/medcl/elasticsearch-analysis-ik/releases
5.1.2、切换到安装es用户,并在es的安装目录下/plugins创建ik
mkdir ‐p /usr/local/es/elasticsearch‐7.6.1/plugins/ik
5.1.3、将下载的ik分词器上传并解压到该目录
cd /usr/local/es/elasticsearch‐7.6.1/plugins/ik
解压 elasticsearch‐analysis‐ik‐7.6.1.zip
5.1.4、重启ElasticSearch
5.1.5、指定IK分词器作为默认分词器
- ES的默认分词设置是standard,这个在中文分词时就比较尴尬了,会单字拆分,比如我搜索关键词“清华大学”,这时候会按“清”,“华”,“大”,“学”去分词,然后搜出来的都是些“清清的河水”,“中华儿女”,“地大物博”,“学而不思则罔”之类的莫名其妙的结果,这里我们就想把这个分词方式修改一下,于是呢,就想到了ik分词器,有两种ik_smart和ik_max_word。
- ik_smart会将“清华大学”整个分为一个词
- ik_max_word会将“清华大学”分为“清华大学”,“清华”和“大学”
修改默认分词方法:ik_max_word):
PUT /indexname
{
"settings" : {
"index" : {
"analysis.analyzer.default.type": "ik_max_word"
}
}
}
6、ES数据管理
- ES是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。
- 然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。
- 在ES中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。ES使用JSON作为文档序列化格式。
- JSON现在已经被大多语言所支持,而且已经成为NoSQL领域的标准格式。
6.1、基本操作
- 创建索引:PUT /索引名称
- 查询索引:GET /索引名称
- 删除索引:DELETE /索引名称
- 添加文档:PUT /索引名称/id
- 修改文档:PUT /索引名称/id
- 查询文档:GET /索引名称/id
- 删除文档:格式: DELETE /索引名称/类型/id
6.2、查询操作
查询当前类型中的所有文档 _search
格式: GET /索引名称/类型/_search
举例: GET /es_db/_doc/_search
SQL: select * from student
条件查询, 如要查询age等于28岁的 _search?q=:**
格式: GET /索引名称/类型/_search?q=*:***
举例: GET /es_db/_doc/_search?q=age:28
SQL: select * from student where age = 28
范围查询, 如要查询age在25至26岁之间的 _search?q=*[ TO **] 注意:TO 必须为大写
格式: GET /索引名称/类型/_search?q=***[25 TO 26]
举例: GET /es_db/_doc/_search?q=age[25 TO 26]
SQL: select * from student where age between 25 and 26
根据多个ID进行批量查询 _mget
格式: GET /索引名称/类型/_mget
举例: GET /es_db/_doc/_mget
{
"ids":["1","2"]
}
SQL: select * from student where id in (1,2)
查询年龄小于等于28岁的 :<=
格式: GET /索引名称/类型/_search?q=age:<=**
举例: GET /es_db/_doc/_search?q=age:<=28
SQL: select * from student where age <= 28
查询年龄大于28前的 :>
格式: GET /索引名称/类型/_search?q=age:>**
举例: GET /es_db/_doc/_search?q=age:>28
SQL: select * from student where age > 28
分页查询 from=&size=
格式: GET /索引名称/类型/_search?q=age[25 TO 26]&from=0&size=1
举例: GET /es_db/_doc/_search?q=age[25 TO 26]&from=0&size=1
SQL: select * from student where age between 25 and 26 limit 0, 1
对查询结果只输出某些字段 _source=字段,字段
格式: GET /索引名称/类型/_search?_source=字段,字段
举例: GET /es_db/_doc/_search?_source=name,age
SQL: select name,age from student
对查询结果排序 sort=字段:desc/asc
格式: GET /索引名称/类型/_search?sort=字段 desc
举例: GET /es_db/_doc/_search?sort=age:desc
SQL: select * from student order by age desc
7、DSL语言高级查询 - 简介 (Query、Filter)
- ES提供了强大的查询语言(DSL),它可以允许我们进行更加强大、复杂的查询,Elasticsearch DSL中有Query与Filter两种
7.1、Query方式查询
Query方式查询,会在ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
1、根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会采用精确匹配
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
POST /es_db/_doc/_search
{
"query": {
"term": {
"name": "admin"
}
}
}
SQL: select * from student where name = 'admin'
2、根据备注信息模糊查询 match, match会根据该字段的分词器,进行分词查询
POST /es_db/_doc/_search
{
"from": 0,
"size": 2,
"query": {
"match": {
"address": "广州"
}
}
}
SQL: select * from user where address like '%广州%' limit 0, 2
3、多字段模糊匹配查询与精准查询 multi_match
POST /es_db/_doc/_search
{
"query":{
"multi_match":{
"query":"张三",
"fields":["address","name"]
}
}
}
SQL: select * from student where name like '%张三%' or address like '%张三%'
4、范围查询
- range:范围关键字
- gte 大于等于
- lte 小于等于
- gt 大于
- lt 小于
- now 当前时间
POST /es_db/_doc/_search
{
"query" : {
"range" : {
"age" : {
"gte":25,
"lte":28
}
}
}
}
SQL: select * from user where age between 25 and 28
5、分页、输出字段、排序综合查询
POST /es_db/_doc/_search
{
"query" : {
"range" : {
"age" : {
"gte":25,
"lte":28
}
}
},
"from": 0,
"size": 2,
"_source": ["name", "age", "book"],
"sort": {"age":"desc"}
}
7.2、Filter过滤器方式查询
Filter过滤器方式查询,它的查询不会计算相关性分值,也不会对结果进行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
POST /es_db/_doc/_search
{
"query" : {
"bool" : {
"filter" : {
"term":{
"age":25
}
}
}
}
}
8、文档映射
ES中映射可以分为动态映射和静态映射
8.1、动态映射
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映射(即关系型数据库的表、字段等),在文档写入Elasticsearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。
动态映射规则如下:
8.2、静态映射
静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类型、分词器等,这种方式称之为静态映射。
1、设置文档映射
PUT /es_db
{
"mappings":{
"properties":{
"name":{"type":"keyword","index":true,"store":true},
"sex":{"type":"integer","index":true,"store":true},
"age":{"type":"integer","index":true,"store":true},
"book":{"type":"text","index":true,"store":true,"analyzer":"ik_smart","search_analyzer":"ik_smart"},
"address":{"type":"text","index":true,"store":true}
}
}
}
8.3、keyword 与 text 映射类型的区别
- keyword 映射 (只能精准查询, 不能分词查询,能聚合、排序)
- text 映射 (能模糊查询, 能分词查询,不能聚合、排序)
9、DSL语言高级查询
9.1、Query DSL概述
- Domain Specific Language 领域专用语言
- Elasticsearch提供了基于JSON的DSL来定义查询。
- DSL由叶子查询子句和复合查询子句两种子句组成 (如上图)。
9.2、无查询条件
- 无查询条件是查询所有,默认是查询所有的,或者使用match_all表示所有
GET /es_db/_doc/_search
{
"query":{
"match_all":{}
}
9.3、有查询条件 - 叶子条件查询(单字段查询条件)
1、模糊匹配
模糊匹配主要是针对文本类型的字段,文本类型的字段会对内容进行分词,对查询时,也会对搜索条件进行分词,然后通过倒排索引查找到匹配的数据,模糊匹配主要通过match等参数来实现
- match : 通过match关键词模糊匹配条件内容
- prefix : 前缀匹配
- regexp : 通过正则表达式来匹配数据
match的复杂用法:match条件还支持以下参数:
- query : 指定匹配的值
- operator : 匹配条件类型
and : 条件分词后都要匹配
or : 条件分词后有一个匹配即可(默认) - minmum_should_match : 指定最小匹配的数量
2、精确匹配
- term : 单个条件相等
- terms : 单个字段属于某个值数组内的值
- range : 字段属于某个范围内的值
- exists : 某个字段的值是否存在
- ids : 通过ID批量查询
9.4、有查询条件 - 组合条件查询(多条件查询)
组合条件查询是将叶子条件查询语句进行组合而形成的一个完整的查询条件
- bool : 各条件之间有and,or或not的关系
must : 各个条件都必须满足,即各条件是and的关系
should : 各个条件有一个满足即可,即各条件是or的关系
must_not : 不满足所有条件,即各条件是not的关系
filter : 不计算相关度评分,它不计算_score即相关度评分,效率更高 - constant_score : 不计算相关度评分
must/filter/shoud/must_not 等的子条件是通过 term/terms/range/ids/exists/match 等叶子条件为参数的
注:以上参数,当只有一个搜索条件时,must等对应的是一个对象,当是多个条件时,对应的是一个数组
9.5、有查询条件 - 连接查询(多文档合并查询)
- 父子文档查询:parent/child
- 嵌套文档查询: nested
9.6、有查询条件 - DSL查询 - query DSL
它们两个的区别如下图:
query DSL
在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”
如何验证匹配很好理解,如何计算相关度呢?ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。
filter DSL
在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”
答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。
过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用must_not或者filter
另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。
Query方式查询:案例
1、根据名称精确查询姓名 term, term查询不会对字段进行分词查询,会采用精确匹配
注意: 采用term精确查询, 查询字段映射类型属于为keyword.
POST /es_db/_doc/_search
{
"query": {
"term": {
"name": "admin"
}
}
SQL: select * from student where name = 'admin'
2、根据备注信息模糊查询 match, match会根据该字段的分词器,进行分词查询
POST /es_db/_doc/_search
{
"from": 0,
"size": 2,
"query": {
"match": {
"address": "广州"
}
}
SQL: select * from user where address like '%广州%' limit 0, 2
3、多字段模糊匹配查询与精准查询 multi_match
POST /es_db/_doc/_search
{
"query":{
"multi_match":{
"query":"张三",
"fields":["address","name"]
}
}
SQL: select * from student where name like '%张三%' or address like '%张三%'
4、未指定字段条件查询 query_string , 含 AND 与 OR 条件
POST /es_db/_doc/_search
{
"query":{
"query_string":{
"query":"广州 OR 长沙"
}
}
5、指定字段条件查询 query_string , 含 AND 与 OR 条件
POST /es_db/_doc/_search
{
"query":{
"query_string":{
"query":"admin OR 长沙",
"fields":["name","address"]
}
}
6、范围查询
POST /es_db/_doc/_search
{
"query" : {
"range" : {
"age" : {
"gte":25,
"lte":28
}
}
}
SQL: select * from user where age between 25 and 28
7、分页、输出字段、排序综合查询
POST /es_db/_doc/_search
{
"query" : {
"range" : {
"age" : {
"gte":25,
"lte":28
}
}
},
"from": 0,
"size": 2,
"_source": ["name", "age", "book"],
"sort": {"age":"desc"}
9.7、有查询条件 - DSL查询 - filter DSL
Filter过滤器方式查询,它的查询不会计算相关性分值,也不会对结果进行排序, 因此效率会高一点,查询的结果可以被缓存。
Filter Context 对数据进行过滤
POST /es_db/_doc/_search
{
"query" : {
"bool" : {
"filter" : {
"term":{
"age":25
}
}
}
}
9.8、总结
- match
match:模糊匹配,需要指定字段名,但是输入会进行分词,比如"helloworld"会进行拆分为hello和world,然后匹配,如果字段中包含hello或者world,或者都包含的结果都会被查询出来,也就是说match是一个部分匹配的模糊查询。查询条件相对来说比较宽松。 - term
term: 这种查询和match在有些时候是等价的,比如我们查询单个的词hello,那么会和match查询结果一样,但是如果查询"hello world",结果就相差很大,因为这个输入不会进行分词,就是说查询的时候,是查询字段分词结果中是否有"hello world"的字样,而不是查询字段中包含"hello world"的字样。当保存数据"hello world"时,elasticsearch会对字段内容进行分词,“hello world"会被分成hello和world,不存在"hello world”,因此这里的查询结果会为空。这也是term查询和match的区别。 - match_phase
match_phase:会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要求一样。以"hello world"为例,要求结果中必须包含hello和world,而且还要求他们是连着的,顺序也是固定的,hello that world不满足,world hello也不满足条件。 - query_string
query_string:和match类似,但是match需要指定字段名,query_string是在所有字段中搜索,范围更广泛。
9.9、对已存在的mapping映射进行修改
- 如果要推倒现有的映射, 你得重新建立一个静态索引
- 然后把之前索引里的数据导入到新的索引里
- 删除原创建的索引
- 为新索引起个别名, 为原索引名
POST _reindex
{
"source": {
"index": "db_index"
},
"dest": {
"index": "db_index_2"
}
}
DELETE /db_index
PU /db_index_2/_alias/db_index
9.10、高亮显示
- 在搜索中,经常需要对搜索关键字做高亮显示,高亮显示也有其常用的参数,在这个案例中做一些常用参数的介绍。
- 现在搜索name字段中包含“手机”的document。并对“手机”做高亮显示,高亮效果使用html标签,并设定字体为红色。如果name数据过长,则只显示前20个字符。
{
"query": {
"bool": {
"should": [{
"match": {
"title": "文章"
}
},
{
"match": {
"content": "文章"
}
}
]
}
},
"highlight": {
"fields": {
"title": {},
"content": {}
}
}
}
}
9.11、手工控制搜索结果精准度
如果在搜索的结果document中,需要remark字段中包含多个搜索词条中的一定比例,可以使用下述语法实现搜索。其中minimum_should_match可以使用百分比或固定数字。百分比代表query搜索条件中词条百分比,如果无法整除,向下匹配(如,query条件有3个单词,如果使用百分比提供精准度计算,那么是无法除尽的,如果需要至少匹配两个单词,则需要用67%来进行描述。如果使用66%描述,ES则认为匹配一个单词即可。)。固定数字代表query搜索条件中的词条,至少需要匹配多少个。
GET /es_db/_search
{
"query": {
"match": {
"remark": {
"query": "java architect assistant",
"minimum_should_match": "68%"
}
}
}
如果使用should+bool搜索的话,也可以控制搜索条件的匹配度。
具体如下:下述案例代表搜索的document中的remark字段中,必须匹配java、developer、assistant三个词条中的至少2个。
GET /es_db/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"remark": "java"
}
},
{
"match": {
"remark": "developer"
}
},
{
"match": {
"remark": "assistant"
}
}
],
"minimum_should_match": 2
}
}
9.12、boost权重控制
- 搜索document中remark字段中包含java的数据,如果remark中包含developer或architect,则包含architect的document优先显示。(就是将architect数据匹配时的相关度分数增加)。
- 一般用于搜索时相关度排序使用。如:电商中的综合排序。将一个商品的销量,广告投放,评价值,库存,单价比较综合排序。在上述的排序元素中,广告投放权重最高,库存权重最低。
GET /es_db/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"remark": "java"
}
}
],
"should": [
{
"match": {
"remark": {
"query": "developer",
"boost" : 1
}
}
},
{
"match": {
"remark": {
"query": "architect",
"boost" : 3
}
}
}
]
}
}
}