Elasticsearch 基本使用(三)条件查询

2023-11-12

简单查询

term

单词查询

  • 对于不分词的字段(数组视同普通字段,查询数组字段时,只要匹配上一项就算匹配)条件直接匹配字段值
  • 对于分词的字段;在字段倒排索引表,仅限分词结果内查找条件值

terms

同样是单词查询;但条件值可以是多个值,效果为 term1 or term2
should : [
{term1…}, {term2…}
]

range

数值范围查询

"range": {
      "FIELD": {
        "gte": 10,
        "lte": 20
      }
    }

match

match 匹配字段,会对条件分词,然后每个词以or的关系在文档倒排索引内进行查询
match:对于不分词的字段直接匹配值;
对于分词的字段,先进行分词得到词典,然后对词典执行tern的组合(or 或 and,默认为 or )

GET bank/_search
{
  "query": {
    "match": {
      "address": "244 Columbus Place"
    },
    "match": {
      "name": {
        "query": "条件值",
        "operator": "and/or"
      }
    }
  }
}

可以看到
在这里插入图片描述
上面两条数据的 address 的相同点就是 都有244。

debug 查看分词结果

GET _analyze
{
  "text": ["244 Columbus Place"]
}

# res 可以看到,拆分成了 244,columbus,place;
# 实际查询条件为 244 or columbus or place
{
  "tokens" : [
    {
      "token" : "244",
      "start_offset" : 0,
      "end_offset" : 3,
      "type" : "<NUM>",
      "position" : 0
    },
    {
      "token" : "columbus",
      "start_offset" : 4,
      "end_offset" : 12,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "place",
      "start_offset" : 13,
      "end_offset" : 18,
      "type" : "<ALPHANUM>",
      "position" : 2
    }
  ]
}

match_phrase

不对条件值分词,直接拿到文档里面找;只要能找到这个完整的关键词就能匹配。
文档字段包含这个词就能匹配
查询连续的多个完整词

GET bank/_search
{
  "query": {
    "match_phrase": {
      "address": "244 Columbus Place"
    }
  }
}

# 可以看到,只查询到一条数据
{
  "took" : 7,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 14.199377,
    "hits" : [
      {
        "_index" : "bank",
        "_type" : "_doc",
        "_id" : "0",
        "_score" : 14.199377,
        "_source" : {
          "account_number" : 0,
          "balance" : 16623,
          "firstname" : "Bradshaw",
          "lastname" : "Mckenzie",
          "age" : 29,
          "gender" : "F",
          "address" : "244 Columbus Place",
          "employer" : "Euron",
          "email" : "bradshawmckenzie@euron.com",
          "city" : "Hobucken",
          "state" : "CO"
        }
      }
    ]
  }
}

match_phrase_prefix

查询多个连续的词(term),最后一个词 以 prefix 查询
举例:name = my name is tony
查询条件值为 my n
match_phrase 查不到数据,因为 n 没有在字段分词找到对应的词
match_phrase_prefix 能查到数据,最后一个条件 值为 n,对n执行前缀查询,所以能查到

match_bool_prefix

条件分词后,前面的词以 term 查询,最后一个以 prefix 查询

should [
term: 条件分词1,
term: 条件分词2,
prefix:最后一个条件词
]

multi_match

友视需要在多个字段上查询相同条件。比如搜索商品关键词,既可以在商品名称上匹配,也可以在品牌名称上匹配

"multi_match": {
  "query": "条件值",
  "fields": ["goods_name", "brand"]
}

复合查询

在实际使用中,往往是在多个条件下查询数据。

bool 查询

query 下使用 bool 聚合多条件,通过组合内部多个条件的逻辑关系,形成最终的查询条件。
bool 内部 must ,must_not,filter,should 之间为与的关系

以下查询条件为:

  • address 分词匹配 244 Columbus Plac age = 29
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "244 Columbus Place"
          }
        },
        {
          "match": {
            "age": 29
          }
        }        
      ]      
    }    
  }
}
标记数据匹配的条件

查询结果还可以标记当前记录,匹配上了哪些条件
在查询中,指定查询条件值时:
_name标记当前条件
实际测试下来,不同查询方式,写法还不太一样

  • term
"term": {
  "age": {
    "value": "30",
    "_name": "age"
  }
}
  • terms
"terms": {
  "age": ["30"],
  "_name": "age"
}
  • match
"match": {
  "name": { 字段名
    "query": "四",
    "_name": "name"
  }
}

在这里插入图片描述
可以看到最后有一个 matched_queries字段,说明本条记录是匹配了哪些条件。
但是,这个机制好像对嵌套查询没效果,后续有机会再了解

bool 子元素区别
  • must: 与 (内部做与运算)
  • must_not:非(内部做 与 运算,最后在外层做非运算)不进行相关性评分,不影响整体评分
  • should:或 (内部做 或运算)
  • filter 过滤器,单纯过滤,先于 上述条件执。,不进行相关性评分,不影响整体评分,会使用过滤器缓存。速度更快。
    每个元素内部,还可以嵌套复杂条件(再来一层bool)

boosting 查询(人为降低指定条件得分)

在bool查询中,我们的查询结果是将 bool 内部的所有条件做 与运算
所有都匹配的数据会查出来,并根据相关性进行计分,默认倒序排列。
boosting 查询,则是
先根据 positive下的条件查询结果并得出一个初始评分,
再根据negative 下的条件匹配查询结果,如果匹配上了,则再根据negative_boost的值对其进行降分的处理,使其排名降低。

# boosting 查询
GET /stu/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match_phrase": {
            "name": {
              "query": "张三",
              "_name": "name"
            }
          }
      },
      "negative": {
        "term": {
            "age": {
              "value": "30",
              "_name": "age"
            }
          }
      },
      "negative_boost": 0.2
    }
  }
}

简单总结,就是 以 positive 查询数据,再以 negative + negative_boost 对结果降分

constant_score 查询(固定得分)

普通的查询相关性分数是es根据相关性确定的,在此基础上,我们可以通过boosting查询降低匹配特定指标的分数。
还有一种,我们可以返回固定分数。
通过前面的学习,我们知道在 bool 查询中 filter 和 must_not 是不计算分数的;因此 constant_score查询其实就是通过 filter查询,然后为其指定固定分数实现。

# constant_score 查询
GET /stu/_search
{
  "query": {
    "constant_score": {
      "filter": { # 查询条件
        "term": {
          "age": "30"
        }
      },
      "boost": 1.2 # 固定分数
    }
  }
}

dis_max 查询(单条件 最高分)

其他查询,最终得分是由所有query综合得分构成。
而dis_max 查询只取评分最高的那一项查询,而忽略其他条件的评分
以下条件查询 name 匹配 张三 或者 hobbies 包含 book 的用户

GET /stu/_search
{
  "query": {
    "dis_max": {
      "queries": [
        {
          "match": {
            "name": "张三"
          }
        },
        {
          "match": {
            "hobbies": "book"
          }
        }
      ]
    }
  }
}

得到以下得分

    "hits" : [
      {
        "_index" : "stu",
        "_type" : "_doc",
        "_id" : "jToE7YgBKFUjhQBivmyC",
        "_score" : 0.9983525,
        "_source" : {
          "id" : 1,
          "name" : "张三",
          "age" : 10,
          "hobbies" : [
            "swimming",
            "walk",
            "drive"
          ],
          "address" : [
            {
              "province" : "500",
              "city" : "023",
              "county" : "1991"
            },
            {
              "province" : "501",
              "city" : "024",
              "county" : "1992"
            }
          ]
        }
      },
      {
        "_index" : "stu",
        "_type" : "_doc",
        "_id" : "jzoE7YgBKFUjhQBi_2zu",
        "_score" : 0.9808291,
        "_source" : {
          "id" : 3,
          "name" : "张三四",
          "age" : 30,
          "hobbies" : [
            "movie",
            "book",
            "swimming"
          ],
          "address" : [
            {
              "province" : "600",
              "city" : "021",
              "county" : "1887"
            },
            {
              "province" : "601",
              "city" : "073",
              "county" : "1953"
            }
          ]
        }
      }
    ]
条件 得分
张三_name 0.9983525
张三_hobbies 0
张三四_name 0.8416345
张三四_hobbies 0.9808291

可以看到,第一条记录虽然只匹配上了 name = 张三,但是它的得分是 0.9983525,
而第二条记录虽然匹配上了两个条件 ,但是单算 name = 张三四 的评分只有 0.8416345,而 单算 hobbies 含有 book 的得分为 0.9808291,因此第二条记录采用了 较高匹配度的 hobbies 的得分。
总体算下来,低于第一条

算上其他 query 的得分

只使用 dis_max 会完全忽略其他query条件的得分,可能导致最终结果,不准确;因此,我们可以算上其他query的得分。
通过 参数 tie_breaker 来指定其他query得分的缩小比例,取值范围 [0, 1],当这个值为1时,其效果了 bool 查询一致。

这里我们将缩小比例设置为0.7,再看看查询的结果

GET /stu/_search
{
  "query": {
    "dis_max": {
      "queries": [
        {
          "match": {
            "name": "张三"
          }
        },
        {
          "match": {
            "hobbies": "book"
          }
        }
      ],
      "tie_breaker": 0.7
    }
  }
}

在这里插入图片描述
可以看到,张三四 在 hobbies 的基础之上,加上 name 的分数已经超越了 张三。
再结合上面表格单项得分,“tie_breaker”: 0.7
张三得分 = 0.9983525 + 0 = 0.9983525
张三四得分 = 0.9808291 + 0.8416345 * 0.7 = 1.56997325
与上图相符。

function_score 查询

使用函数自定义评分逻辑;可以使用内置函数或脚本完全自定义评分逻辑。
内置函数

  • weight 对当前分值做 乘法,实现 增加或减少
  • random_score :生成随机分数
  • field_value_factor :将文档指定字段(数值或者可转化为数值)纳入得分计算。
  • 衰减函数 - linear,exp,gauss 等
  • script_score 使用脚本,完全自定义评分逻辑

我们还可以使用 functions 为不同匹配条件指定不同的计分逻辑;匹配上了执行对应的计分逻辑,未匹配上的得1分,未匹配上的数据也会展示出来
functions 外面的查询及其评分只展示匹配上的数据;如果外面没有过滤,只在 functions 内进行查询和评分,那么评分逻辑只作用于匹配上的数据,未匹配上的数据统统1分
自定义函数有个计分计算方式字段 “boost_mode”: “multiply” 默认是乘法(weight及field 方式都是乘以现有分数)。
在这里插入图片描述

weight 成倍增减现有得分
GET /stu/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "name": "张三"
        }
      },
      "weight": 0.5,
      "boost_mode": "multiply"
    }
  }
}

两条数据
在这里插入图片描述

random_score 随机得分
GET /stu/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "name": "张三"
        }
      },
      "random_score": {}
    }
  }
}

两条数据,随机得分
在这里插入图片描述

指定字段(数值或者可转为数值)纳入计分
GET /stu/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "name": "张三"
        }
      },
      "field_value_factor": {
        "field": "age"
      }
    }
  }
}

以下得分 = 现有得分 * 字段值 (age)* 比例(factor 默认为1) = 0.9983525 * 30 * 1 = 25.249035
在这里插入图片描述

自定义脚本得分

使用脚本完全自定义得分逻辑

直接以age为得分

script_score.script :指定得分计算方式,直接取 age 的值
boost_mode:replace;默认是 multiply,还是与age做乘法;使用replace,则是直接替换原有的分数而不做乘法。

# 直接以age得分
GET /stu/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "name": "张三"
        }
      },
      "script_score": {
        "script": "doc['age'].value"
      },
      "boost_mode": "replace"
    }
  }
}

因此得到分数分别为二者的 age
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Elasticsearch 基本使用(三)条件查询 的相关文章

随机推荐

  • 【Visual Studio】调试过程中VS卡死无响应

    最近在使用vs2022 debug调试过程中 经常出现vs2022直接卡死无响应 解决方案 第一种原因 是加载符号导致 调试 选项 符号 1 取消勾选 xxx 符号服务器 2 选择 仅加载指定的模块 第二种情况 VS卡死后 把崩溃dmp导出
  • 实时操作系统-与QNX比较-qnx系统优势-qnx性能分析-qnx系统性能分析

    锋影 e mail 174176320 qq com LynxOS QNX Linux的分析和比较 本文对四种实时操作系统 RTOS 特性进行分析和比较 它们是 Lynx实时系统公司的LynxOS QNX软件系统有限公司的QNX以及两种具有
  • 解决爬虫登陆电信密码加密问题

    遇见问题 写爬虫抓取电信数据 在登陆时发现密码加密问题 扒出加密函数如下 fn aesEncrypt function n var t CryptoJS MD5 login 189 cn i CryptoJS enc Utf8 parse
  • 使用kettle转换中的JavaScript对密码进行加密和解密

    日常开发中 为了确保账号和密码的安全 时常要对密码进行加密和解密 然而kettle是怎么对密码进行加密和解密的呢 下面的代码需要再转换中的JavaScript中运行 var encrypted password not encrypted
  • JDBC操作postgresql(javaweb)

    首先 postgresql的几个常见 语句结尾一定要加分号 语句结尾一定要加分号 语句结尾一定要加分号 如果是变量不要加引号 sql语句要加引号 1 常见命令 先进入安装的bin目录下 psql exe U postgres 连接数据库 h
  • linux:cloudflare证书申请及应用到nginx

    参考 免费申请网站SSL证书 有效期15年 全站开启https 哔哩哔哩 bilibili 总结 登陆www cloudflare com 注册账号 Add a Site 增加站点 站点设置完毕后Add record 记住这个Proxy s
  • JAVA之单元测试:Junit框架

    单元测试 单元测试就是针对最小的功能单元编写测试代码 Java程序最小的功能单元是方法 因此 单元测试就是针对Java方法的测试 进而检查方法的正确性 目前测试方法是怎么进行的 存在什么问题 1 只有一个main方法 如果一个方法的测试失败
  • BIP上传模版报错 SBL-EAI-04308

    问题 BIP里面上传模版时报如下错误 Siebel 1 0 Web 服务 的操作 SBL EAI 04308 IDS EAI WS OD FAULT 2 对象管理器错误 0 Web 服务 的操作 SBL EAI 04308 IDS EAI
  • win10双屏锁屏后再登陆导致副屏窗口全部移到主屏的解决方法

    win10双屏锁屏后再登陆导致副屏窗口全部移到主屏的解决方法 其实是锁屏后屏幕关闭了 在重新打开时 会将所有窗口移动到主屏幕 解决方法 修改锁屏后屏幕关闭时间 具体请看http www xitongcheng com jiaocheng w
  • 字符串哈希

    字符串哈希 我们可以把一个字符串哈希处理成一个数字 具体做法 将字符串看作是一个p进制数 p大于字符的ascii码值 acbd哈希成数字是 a p 3 c p 2 b p 1 d p 0 modQ p一般取131或者13331 Q取2e64
  • Docker学习笔记

    五 Docker 1 简介 Docker是一个开源的应用容器引擎 是一个轻量级容器技术 Docker支持将软件编译成一个镜像 然后在镜像中各种软件做好配置 将镜像发布出去 其他使用者可以直接使用这个镜像 运行中的这个镜像称为容器 容器启动是
  • 微信小程序静态初步

    社团微信小程序 1 由于兴趣驱动 一直在学习微信小程序 由于之前一直学习Java 但是大三第一学期即将结尾 所以为了能让下学期的学习减少工作量所以就打算利用闲散时间开发小程序 于是就拿社团为例子 自己一步步摸索 现在只是初步学习 所以这些天
  • mysql-Innodb事务隔离级别-repeatable read详解(转)

    mysql Innodb事务隔离级别 repeatable read详解 转 一 事务隔离级别 ANSI ISO SQL标准定义了4中事务隔离级别 未提交读 read uncommitted 提交读 read committed 重复读 r
  • vim配置经典

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 在终端 输入以下命令来编辑vimrc配置文件 sudo vim etc vim vimrc 或者 sudo gedit etc vim vimrc 将其复制粘贴进去 Des
  • GeoDa:入门基础

    前言 GeoDa是一个免费的开源软件工具 用于空间数据分析 它旨在通过探索和建模空间模式来促进数据分析的新见解 GeoDa是由Luc Anselin博士和他的团队开发的 该项目为探索性空间数据分析 ESDA 方法提供了用户友好的图形界面 例
  • mysql中join源码分析,MySQL中Join算法实现原理分析[图]

    在MySQL 中 只有一种 Join 算法 就是大名鼎鼎的 Nested Loop Join 他没有其他很多数据库所提供的 Hash Join 也没有 Sort Merge Join 顾名思义 Nested Loop Join 实际上就是通
  • 把二叉树转换成树(代码实现)

    前言 相信大家都知道二叉树如何转化成树 但是让你用代码实现 却发现自己无从下手 下面我将用代码实现 思想 树用二叉树来存储的话 那么类型是 左儿子 右兄弟 即二叉树某节点和它的左儿子在树中的关系也是父子关系 而与右儿子在树中的关系是兄弟关系
  • 机器视觉中非常好的github仓库

    AwesomeComputerVision Multi Object Tracking Paper List https github com SpyderXu multi object tracking paper list awesom
  • Oracle VM VirtualBox 不显示64位系统 linux 64 redhat 64

    打开BIOS里的虚拟化技术 修改bios中的virtualization 设为ENABLED
  • Elasticsearch 基本使用(三)条件查询

    条件查询 简单查询 term terms range match debug 查看分词结果 match phrase match phrase prefix match bool prefix multi match 复合查询 bool 查