前言

有时我们在搜索电影的时候,包含了多个条件,比如主演是周星驰,打分8分以上,上映时间是1990年~2001年的,那么Elasticsearch又该如何帮我们做查询呢?这里我们可以用 bool 查询来实现需求。这种查询将多查询组合在一起,成为用户自己想要的 bool 查询。

bool 查询

一个 bool 查询,可以包含一个或多个查询语句进行组合。

有4种参数

  • must:文档必须匹配这些条件才能被包含进来。贡献算分。
  • should:文档选择性匹配,如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。贡献算分。
  • must_not:文档必须不匹配这些条件才能被包含进来。
  • filter:必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。不贡献算分。

基本语法

  • bool 里面的子查询继续嵌套 bool 查询
  • 子查询可以以任意顺序出现
  • 如果没有 must 语句,那么至少需要能够匹配其中的一条 should 语句。但如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。
  • must等可以跟一个对象(“{}”),也可以跟数组(“[]”)
  1. {
  2. "bool": {
  3. "must": { "match": { "title": "how to make millions" }},
  4. "must_not": { "match": { "tag": "spam" }},
  5. "should": [
  6. { "match": { "tag": "starred" }}
  7. ],
  8. "filter": {
  9. "bool": {
  10. "must": [
  11. { "range": { "date": { "gte": "2014-01-01" }}},
  12. { "range": { "price": { "lte": 29.99 }}}
  13. ],
  14. "must_not": [
  15. { "term": { "category": "ebooks" }}
  16. ]
  17. }
  18. }
  19. }
  20. }

一个航班查询的例子,搜索去往美国的,当地天气是晴朗的,不从日本出发的,票价小于等于1000的航班。

  1. GET kibana_sample_data_flights/_search
  2. {
  3. "size": 5,
  4. "query": {
  5. "bool": {
  6. "must": [
  7. {
  8. "term": {
  9. "DestCountry": "US"
  10. }
  11. },
  12. {
  13. "term": {
  14. "DestWeather": "Sunny"
  15. }
  16. }
  17. ],
  18. "must_not": {
  19. "term": {
  20. "OriginCountry": "JP"
  21. }
  22. },
  23. "filter": {
  24. "range": {
  25. "AvgTicketPrice": {
  26. "lte": 1000
  27. }
  28. }
  29. }
  30. }
  31. }
  32. }

控制相关性

那么多个字段的查询,我们该如何影响其相关性的算分呢?

层级嵌套

同一层级下的字段是竞争关系,具有相同权重,可以通过嵌套改变对算分的影响。

  1. GET animals/_search
  2. {
  3. "query": {
  4. "bool": {
  5. "should": [
  6. {"term": {"text": "brown"}},
  7. {"term": {"text": "red"}},
  8. {"term": {"text": "quick"}},
  9. {"term": {"text": "dog"}}
  10. ]
  11. }
  12. }
  13. }
  14. GET animals/_search
  15. {
  16. "query": {
  17. "bool": {
  18. "should": [
  19. {"term": {"text": "brown"}},
  20. {"term": {"text": "red"}},
  21. {"bool": {
  22. "should": [
  23. {"term": {"text": "quick"}},
  24. {"term": {"text": "dog"}}
  25. ]
  26. }
  27. }
  28. ]
  29. }
  30. }
  31. }

boosting

控制字段的权重,可以使用boosting,默认值是1,可正可负。

  • 当boost>1时,打分的相关性相对提升
  • 当0<boost<1时,打分的相关性相对降低
  • 当boost<0时,贡献负分

精简语法,可以在match里面指定boost,比如上面的航班信息DestCountry部分字段设置权重。

  1. GET kibana_sample_data_flights/_search
  2. {
  3. "explain": true,
  4. "size": 5,
  5. "query": {
  6. "bool": {
  7. "must": [
  8. {
  9. "match": {
  10. "DestCountry": {
  11. "query": "US",
  12. "boost": 10
  13. }
  14. }
  15. },
  16. {
  17. "term": {
  18. "DestWeather": "Sunny"
  19. }
  20. }
  21. ],
  22. "must_not": {
  23. "term": {
  24. "OriginCountry": "JP"
  25. }
  26. },
  27. "filter": {
  28. "range": {
  29. "AvgTicketPrice": {
  30. "lte": 1000
  31. }
  32. }
  33. }
  34. }
  35. }
  36. }

完整boosting语法,positive正向作用,negative负向作用,negative_boost负向作用的权重,可以用来降级匹配的文档,不像“NOT”逻辑运算直接去除相关的文档

  1. GET movies/_search
  2. {
  3. //"explain": true,
  4. "query": {
  5. "boosting": {
  6. "positive": {
  7. "term": {
  8. "title": {
  9. "value": "beautiful"
  10. }
  11. }
  12. },
  13. "negative": {
  14. "term": {
  15. "title": {
  16. "value": "mind"
  17. }
  18. }
  19. },
  20. "negative_boost": 0.2
  21. }
  22. }
  23. }

constant_score 查询

尽管没有 bool 查询使用这么频繁,constant_score 查询也是我们工具箱里有用的查询工具。它将一个不变的常量评分应用于所有匹配的文档。它被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。

  1. GET movies/_search
  2. {
  3. "query": {
  4. "constant_score": {
  5. "filter": {
  6. "term": {
  7. "title": "beautiful"
  8. }
  9. }
  10. }
  11. }
  12. }

参考资料

Elasticsearch 复合查询——多字符串多字段查询的更多相关文章

  1. Hibernate 多表查询 - Criteria添加子字段查询条件 - 出错问题解决

    Criteria 查询条件如果是子对象中的非主键字段会报 could not resolve property private Criteria getCriteria(Favorite favori ...

  2. Elasticsearch+Mongo亿级别数据导入及查询实践

    数据方案: 在Elasticsearch中通过code及time字段查询对应doc的mongo_id字段获得mongodb中的主键_id 通过获得id再进入mongodb进行查询   1,数据情况: ...

  3. ElasticStack学习(十):深入ElasticSearch搜索之QueryFiltering、多/单字符串的多字段查询

    一.复合查询 1.在ElasticSearch中,有Query和Filter两种不同的Context.Query Context进行了相关性算分,Filter Context不需要进行算分,同时可以利 ...

  4. ElasticSearch 学习记录之ES查询添加排序字段和使用missing或existing字段查询

    ES添加排序 在默认的情况下,ES 是根据文档的得分score来进行文档额排序的.但是自己可以根据自己的针对一些字段进行排序.就像下面的查询脚本一样.下面的这个查询是根据productid这个值进行排 ...

  5. Mysql查询用逗号分隔的字段-字符串函数FIND_IN_SET(),以及此函数与in()函数的区别

    查询用逗号分隔的字段,可以用字符串函数FIND_IN_SET(): 查询数据库表中某个字段(值分行显示),可以用函数in(). 今天工作中遇到一个问题,就是用FIND_IN_SET()函数解决的. 第 ...

  6. Elasticsearch 单字符串多字段查询

    前言 有些时候,我们搜索的时候,只会提供一个输入框,但是会查询相关的多个字段,典型的如Google搜索,我们该如何用 Elasticsearch 如何实现呢? 实例 从单字符串查询的实例说起 创建测试 ...

  7. [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优

    最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/1 { "title": " ...

  8. [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优(转)

    最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/1 { "title": " ...

  9. ElasticSearch权威指南学习(结构化查询)

    请求体查询 简单查询语句(lite)是一种有效的命令行adhoc查询.但是,如果你想要善用搜索,你必须使用请求体查询(request body search)API. 空查询 我们以最简单的 sear ...

随机推荐

  1. leetcode31 下一个排列 字典序

    数字的字典序就是比大小 先想几个例子  123_>132  1243-> 1324 ,12453-> 12534 1.不可排的序列就是降序序列 2.两个相同长度的串比大小,前面相同, ...

  2. Python 相关

    循环使用迭代器 Python中使用for循环时,内置容器的默认循环都是有迭代器的.使用迭代器每次只会读出一小部分到内存,不断往后next. 通常建议在没有必要的情况下不使用for key,value ...

  3. 2016 最新的 树莓派3 Raspberry Pi 3 上手评测 图解教程 新手必看!(VNC 安装,启动,关闭)

    1.png . 官方教程: INSTALLING OPERATING SYSTEM IMAGES: https://www.raspberrypi.org/documentation/installa ...

  4. 开放式 Web 应用程序安全性项目 OWASP

    开放式 Web 应用程序安全性项目 OWASP Open Web Application Security Project (OWASP) OWASP 基金会是谁? Open Web Applicat ...

  5. jQuery 使用注意事项 与 小技巧(tips)

    jQuery 使用注意事项 与 小技巧(tips) 1 $( document ).ready() https://learn.jquery.com/using-jquery-core/documen ...

  6. cookie all in one

    cookie all in one credentials: "include" https://developers.google.com/web/updates/2015/03 ...

  7. TypedArray & ArrayBuffer

    TypedArray & ArrayBuffer Type Each element size in bytes Int8Array 1 Uint8Array 1 Uint8ClampedAr ...

  8. js & void & undefined & null

    js & void & undefined & null The void operator evaluates the given expression and then r ...

  9. deep copy & deep merge

    deep copy & deep merge JSON.parse(JSON.stringify(obj)); lodash https://lodash.com/docs/ https:// ...

  10. nasm astrstr函数 x86

    xxx.asm: %define p1 ebp+8 %define p2 ebp+12 %define p3 ebp+16 section .text global dllmain export as ...