搜索是ES最最核心的内容,没有之一。前面章节的内容,索引、动态映射、分词器等都是铺垫,最重要的就是最后点击搜索这一下。下面我们就看看点击搜索这一下的背后,都做了哪些事情。

分数(score)

ES的搜索结果是按照相关分数的高低进行排序的,咦?! 怎么没说搜索先说搜索结果的排序了?咱们这里先把这个概念提出来,因为在搜索的过程中,会计算这个分数。这个分数代表了这条记录匹配搜索内容的相关程度。分数是一个浮点型的数字,对应的是搜索结果中的_score字段,分数越高代表匹配度越高,排序越靠前。

在ES的搜索当中,分为两种,一种计算分数,而另外一种是不计算分数的。

查询(query context)

查询,代表的是这条记录与搜索内容匹配的怎么样,除了决定这条记录是否匹配外,还要计算这条记录的相关分数。这个和咱们平时的查询是一样的,比如我们搜索一个关键词,分词以后匹配到相关的记录,这些相关的记录都是查询的结果,那这些结果谁排名靠前,谁排名靠后呢?这个就要看匹配的程度,也就是计算的分数。

过滤(filter context)

过滤,代表的含义非常的简单,就是YES or NO,这条记录是否匹配查询条件,它不会计算分数。频繁使用的过滤还会被ES加入到缓存,以提升ES的性能。下面我们看一个查询和过滤的例子,这个也是ES官网中的例子。

GET /_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Search" }},
{ "match": { "content": "Elasticsearch" }}
],
"filter": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}

我们看一下请求的路径/_search,这个是请求的路径,而请求的方法是GET,我们再看请求体中,有一个query,这个代表着查询的条件。而bool中的must被用作query context,它在查询的时候会计算记录匹配的相关分数。filter中的条件用作过滤,只会把符合条件的记录检索出来,不会计算分数。

组合查询

组合查询包含了其他的查询,像我们前面提到的query contextfilter context。在组合查询中,分为很多种类型,我们挑重点的类型给大家介绍一下。

Boolean Query

boolean查询,前面我们写的查询语句就是一个boolean查询,boolean查询中有几个关键词,表格如下:

关键词 描述
must 必须满足的条件,而且会计算分数,
filter 必须满足的条件,不会计算分数
should 可以满足的条件,会计算分数
must_not 必须不满足的条件,不会计算分数

我们看看下面的查询语句:

POST _search
{
"query": {
"bool" : {
"must" : {
"term" : { "user" : "kimchy" }
},
"filter": {
"term" : { "tag" : "tech" }
},
"must_not" : {
"range" : {
"age" : { "gte" : 10, "lte" : 20 }
}
},
"should" : [
{ "term" : { "tag" : "wow" } },
{ "term" : { "tag" : "elasticsearch" } }
],
"minimum_should_match" : 1,
"boost" : 1.0
}
}
}

上面的查询是一个典型的boolean组合查询,里边的关键词都用上了。很多小伙伴们可能对mustshould的区别不是很了解,must是必须满足的条件,我们的例子中must里只写了一个条件,如果是多个条件,那么里边的所有条件必须满足。而should就不一样了,should里边现在列出了两个条件,并不是说这两个条件必须满足,到底需要满足几个呢?我们看一下下面的关键字minimum_should_match,从字面上我们就可以看出它的含义,最小should匹配数,在这里设置的是1,也就是说,should里的条件只要满足1个,就算匹配成功。在boolean查询中,如果存在一个should条件,而没有filtermust条件的话,那么minimum_should_match的默认值是1,其他情况默认值是0。

我们再看一个实际的例子吧,还记得前面我们创建的ik_index索引吗?索引中存在着几条数据,数据如下:

_index _type _id ▲_score id title desc
ik_index _doc fEsN-HEBZl0Dh1ayKWZb 1 1 苹果 苹果真好吃
ik_index _doc 2 1 1 香蕉 香蕉真好吃
ik_index _doc 1 1 1 香蕉 香蕉真好吃
ik_index _doc 3 1 1 橘子 橘子真好吃
ik_index _doc 4 1 1 桃子 桃子真好吃

只有5条记录,我们新建一个查询语句,如下:

POST /ik_index/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"desc":"香蕉好吃"
}
}
]
}
},
"from":0,
"size":10,
}

我们查询的条件是desc字段满足香蕉好吃,由于我们使用的ik分词器,查询条件香蕉好吃会被分词为香蕉好吃,但是5的数据的desc中都有好吃字段,所有5条数据都会被查询出来,我们执行一下,看看结果:

_index _type _id ▲_score id title desc
ik_index _doc 2 0.98773474 1 香蕉 香蕉真好吃
ik_index _doc 1 0.98773474 1 香蕉 香蕉真好吃
ik_index _doc 3 0.08929447 1 橘子 橘子真好吃
ik_index _doc 4 0.08929447 1 桃子 桃子真好吃
ik_index _doc fEsN-HEBZl0Dh1ayKWZb 0.07893815 1 苹果 苹果真好吃

哈哈,5条数据全部查询出来了,和我们的预期是一样的,但是,我们需要注意一点的是_score字段,它们的分数是不一样的,我们的查询条件是香蕉好吃,所以既包含香蕉又包含好吃的数据分数高,我们看到分数到了0.98,而另外3条数据只匹配了好吃,所以分数只有0.7,0.8。

Boosting Query

这个查询比较有意思,它有两个关键词positivenegativepositive是“正”,所有满足positive条件的数据都会被查询出来,negative是“负”,满足negative条件的数据并不会被过滤掉,而是会扣减分数。那么扣减分数要扣减多少呢?这里边有另外一个字段negative_boost,这个字段是得分的系数,它的分数在0~1之间,满足了negative条件的数据,它们的分数会乘以这个系数,比如这个系数是0.5,原来100分的数据如果满足了negative条件,它的分数会乘以0.5,变成50分。我们看看下面的例子,

POST /ik_index/_search
{
"query": {
"boosting": {
"positive": {
"term": {
"desc": "好吃"
}
},
"negative": {
"term": {
"desc": "香蕉"
}
},
"negative_boost": 0.5
}
}
}

positive条件是好吃,只要desc中有“好吃”的数据都会被查询出来,而negative的条件是香蕉,只要desc中包含“香蕉”的数据都会被扣减分数,扣减多少分数呢?它的得分将会变为原分数*0.5。我们执行一下,看看效果,

index type _id score _source.id source.title source.desc
ik_index _doc 3 0.08929447 1 橘子 橘子真好吃
ik_index _doc 4 0.08929447 1 桃子 桃子真好吃
ik_index _doc fEsN-HEBZl0Dh1ayKWZb 0.07893815 1 苹果 苹果真好吃
ik_index _doc 2 0.044647235 1 香蕉 香蕉真好吃
ik_index _doc 1 0.044647235 1 香蕉 香蕉真好吃

我们可以看到前3条数据的分数都在0.09左右,而后两条的数据在0.044左右,很显然,后两条数据中的desc包含香蕉,它们的得分会乘以0.5的系数,所以分数只有前面数据的分数的一半。

全文检索

在前面几节的内容中,我们介绍过,只有字段的类型是text,才会使用全文检索,全文检索会使用到分析器,在我们的ik_index索引中,titledesc字段都是text类型,所以,这两个字段的搜索都会使用到ik中文分词器。全文检索比起前面的组合检索要简单一点,当然,在ES的官方文档中,全文检索中的内容还是挺多的,在这里我们只介绍一个标准的全文检索。

我们看看下面的语句,

POST /ik_index/_search
{
"query": {
"match": {
"desc": {
"query": "苹果"
}
}
}
}

在请求体中,match代替了之前的boolmatch是标准的全文索引的查询。match后面跟的字段是要查询的字段名,在咱们的例子中,查询的字段是desc,如果有多个字段,可以列举多个。desc字段里,query就是要查询的内容。我们还可以在字段中指定分析器,使用analyzer关键字,如果不指定,默认就是索引的分析器。我们执行一下上面的查询,结果如下:

index type _id score source.id source.title source.desc
ik_index _doc fEsN-HEBZl0Dh1ayKWZb 1.2576691 1 苹果 苹果真好吃

我们可以看到相应的数据已经检索出来了。

最后

在ES中,检索的花样是比较多的,这里也不能一一给大家介绍了,只介绍一些最基本、最常用的查询功能。下一篇我们看一下ES的聚合查询功能。

ES[7.6.x]学习笔记(九)搜索的更多相关文章

  1. [转载]SharePoint 2013搜索学习笔记之搜索构架简单概述

    Sharepoint搜索引擎主要由6种组件构成,他们分别是爬网组件,内容处理组件,分析处理组件,索引组件,查询处理组件,搜索管理组件.可以将这6种组件分别部署到Sharepoint场内的多个服务器上, ...

  2. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  3. MDX导航结构层次:《Microsoft SQL Server 2008 MDX Step by Step》学习笔记九

    <Microsoft SQL Server 2008 MDX Step by Step>学习笔记九:导航结构层次   SQL Server 2008中SQL应用系列及BI笔记系列--目录索 ...

  4. python3.4学习笔记(九) Python GUI桌面应用开发工具选择

    python3.4学习笔记(九) Python GUI桌面应用开发工具选择 Python GUI开发工具选择 - WEB开发者http://www.admin10000.com/document/96 ...

  5. Go语言学习笔记九: 指针

    Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...

  6. go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin)

    目录 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin) zipkin使用demo 数据持久化 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin ...

  7. Python学习笔记九

    Python学习笔记之九 为什么要有操作系统 管理硬件,提供接口. 管理调度进程,并且将多个进程对硬件的竞争变得有序. 操作系统发展史 第一代计算机:真空管和穿孔卡片 没有操作系统,所有的程序设计直接 ...

  8. vue学习笔记(九)vue-cli中的组件通信

    前言 在上一篇博客vue学习笔记(八)组件校验&通信中,我们学会了vue中组件的校验和父组件向子组件传递信息以及子组件通知父组件(父子组件通信),上一篇博客也提到那是对组件内容的刚刚开始,而本 ...

  9. C#线程学习笔记九:async & await入门二

    一.异步方法返回类型 只能返回3种类型(void.Task和Task<T>). 1.1.void返回类型:调用方法执行异步方法,但又不需要做进一步的交互. class Program { ...

随机推荐

  1. 【Python可视化】使用Pyecharts进行奥运会可视化分析~

    项目全部代码 & 数据集都可以访问我的KLab --[Pyecharts]奥运会数据集可视化分析-获取,点击Fork即可- 受疫情影响,2020东京奥运会将延期至2021年举行: 虽然延期,但 ...

  2. 【Inno Setup】Pascal 脚本 ---- 事件函数

    转载 事件函数 Inno Setup支持以下函数和过程. 1. [安装初始化]该函数在安装程序初始化时调用,返回False 将中断安装,True则继续安装,测试代码如下: function Initi ...

  3. AtomineerUtils使用说明

    AtomineerUtils使用说明 VS2015PluginCrackAtomineer 介绍 AtomineerUtils 是国外的一款用于生成源代码注释的一款 VS 插件工具. 这款插件,支持 ...

  4. java 8中 predicate chain的使用

    目录 简介 基本使用 使用多个Filter 使用复合Predicate 组合Predicate Predicate的集合操作 总结 java 8中 predicate chain的使用 简介 Pred ...

  5. 三、通过Vue基础属性做一个Table的增加、删除、姓名音位吗查询

    html头文件包括css,和vue.js的文件的引用 <!DOCTYPE html> <html lang="en"> <head> <m ...

  6. axios的使用小技巧:如何绕过字符串拼接,直接传递对象

     Vue.js官方推荐使用axios作为发送http请求的工具,在使用axios中,有些小技巧是不容易发现的.当我们不知道这些技巧时,我们可能会使用其他"奇技淫巧",比如,我们很容 ...

  7. 在okhttp的callback回调中加Toast出现Cant create handler inside hread that has not called Looper.prepare()...

    2019独角兽企业重金招聘Python工程师标准>>> 分析:callback中回调的response方法中还是在子线程中运行的,所以要调取Toast必须回到主线程中更新ui 解决方 ...

  8. Centos 6.5升级gcc : 源码安装 + rpm安装

    1. 前言 采用Centos 6.5默认的gcc版本为4.4.7,不支持c++ 11,需要升级: 首先想到用yum命令:执行yum update gcc-c++或yum update g++ 显示没有 ...

  9. P3306 [SDOI2013]随机数生成器(bzoj3122)

    洛谷 bzoj 特判+多测真恶心 . \(0\le a\le P−1,0\le b\le P−1,2\le P\le 10^9\) Sample Input 3 7 1 1 3 3 7 2 2 2 0 ...

  10. MySQL 中 on与where筛选条件的区别

    在两张表连接的时候才会有on的筛选条件,那么on和where的区别是什么呢? 在inner join中是没有区别的,但是在左连接和右连接中,区别就体现出来了,下面以左连接为例: 1.用on的时候,只对 ...