前言

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

bool 查询

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

有4种参数

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

基本语法

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

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

GET kibana_sample_data_flights/_search
{
"size": 5,
"query": {
"bool": {
"must": [
{
"term": {
"DestCountry": "US"
}
},
{
"term": {
"DestWeather": "Sunny"
}
}
],
"must_not": {
"term": {
"OriginCountry": "JP"
}
},
"filter": {
"range": {
"AvgTicketPrice": {
"lte": 1000
}
}
}
}
}
}

控制相关性

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

层级嵌套

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

GET animals/_search
{
"query": {
"bool": {
"should": [
{"term": {"text": "brown"}},
{"term": {"text": "red"}},
{"term": {"text": "quick"}},
{"term": {"text": "dog"}}
]
}
}
} GET animals/_search
{
"query": {
"bool": {
"should": [
{"term": {"text": "brown"}},
{"term": {"text": "red"}},
{"bool": {
"should": [
{"term": {"text": "quick"}},
{"term": {"text": "dog"}}
]
}
}
]
}
}
}

boosting

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

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

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

GET kibana_sample_data_flights/_search
{
"explain": true,
"size": 5,
"query": {
"bool": {
"must": [
{
"match": {
"DestCountry": {
"query": "US",
"boost": 10
}
}
},
{
"term": {
"DestWeather": "Sunny"
}
}
],
"must_not": {
"term": {
"OriginCountry": "JP"
}
},
"filter": {
"range": {
"AvgTicketPrice": {
"lte": 1000
}
}
}
}
}
}

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

GET movies/_search
{
//"explain": true,
"query": {
"boosting": {
"positive": {
"term": {
"title": {
"value": "beautiful"
}
}
},
"negative": {
"term": {
"title": {
"value": "mind"
}
}
},
"negative_boost": 0.2
}
}
}

constant_score 查询

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

GET movies/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"title": "beautiful"
}
}
}
}
}

参考资料

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. Eazfuscator.NET(.net混淆工具)

    软件功能 调试支持: 在你的程序集被Eazfuscator.NET混淆后,它不会成为不可调试混乱的砖块.你总是可以得到一个行号,出现未处理的异常,查看可读的堆栈跟踪,甚至附加调试器来遍历你的模糊代码. ...

  2. flagcounter 被禁用...

    源地址 https://s11.flagcounter.com/count2/arWz/bg_FFFFFF/txt_000000/border_CCCCCC/columns_2/maxflags_14 ...

  3. C++中main函数的返回值一定要是int

    因为大学上课时候,经常是在主函数中做处理,直接用cout语句输出到显示设备,所以一直在用void main(). 直到后面具体编程的时候,才发现void main()这种用法是按 C89(C语言的早期 ...

  4. CSS3实现 垂直居中 水平居中 的技巧

    1 1 1 How To Center Anything With CSS Front End posted by Code My Views 1 Recently, we took a dive i ...

  5. how to input special symbol in macOS

    how to input special symbol in macOS 如何在 macOS 中输入特殊符号 1024 ≈ 1000 2^10 == 1024 约等于 1000, 方便用来表示 Opt ...

  6. mongodb & vue & node.js

    mongodb mongodb & vue & node.js https://docs.mongodb.com/manual/tutorial/install-mongodb-on- ...

  7. 找出 int 数组的平衡点 & 二叉树 / 平衡二叉树 / 满二叉树 / 完全二叉树 / 二叉查找树

    找出 int 数组的平衡点 左右两边和相等, 若存在返回平衡点的值(可能由多个); 若不存在返回 -1; ``java int [] arr = {2,3,4,2,4}; ```js const ar ...

  8. PM2 in depth

    PM2 in depth ecosystem.config.js module.exports = { apps : [{ name: "app", script: ". ...

  9. Flutter使用WebSockets

    文档 注意是WebSockets而不是socket.io install dependencies: web_socket_channel: demo import 'dart:convert'; i ...

  10. BGV再度爆发,流通市值破500万美金!

    BGV似乎以超乎寻常的姿态,开启了爆发的模式.这两天,BGV一路上涨,日内最高涨至548.78美金,24小时成交额达到了98.07万美金,24小时成交量达到1844.93枚BGV,流通市值更是突破了5 ...