当前位置: 首页 > article >正文

es 3期 第13节-多条件组合查询实战运用

#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。
#### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性,任何企图直接替代严格事务性场景的应用项目都会失败!!!

##### 索引字段与属性都属于静态设置,若后期变更历史数据需要重建索引才可生效
##### 对历史数据无效!!!!
##### 一定要重建索引!!!!
 

### 组合查询分类
## bool:布尔组合
## boost:加权
## constant:固定分值
## dis_max:单字符多字段组合
## function:函数脚本组合


## bool 逻辑条件
## bool逻辑条件是组合查询,最常用的,也是必须掌握的,DSL查询与SQL不一,传统查询里面的多条件组合通过观关键字组合,这里采用的是以下关键字
# 关键字            说明
# must              必须包含,类同Mysq1关键字 and ,计算分值
# should            可选包含,类同 Mysql关键字 or
# filter            必须包含,类同Mysql关键字 and,不计算分值
# must not          不包含,类同 Mysql 不等于关键字
# mixed 水平组合    混合以上,类同Mysgl多个条件平级组合
# mixed 嵌套组合    混合以上,类同Mysgl 多个括号组合条件

DELETE kibana_sample_data_flights_reindex
# 复制一份航班数据用于查询
# reindex后新索引字段是推断出来的,原来的keyword类型会被推断为text
POST _reindex
{
  "source": {
    "index": "kibana_sample_data_flights"
  },
  "dest": {
    "index": "kibana_sample_data_flights_reindex"
  }
}
GET kibana_sample_data_flights
GET kibana_sample_data_flights_reindex

## 最多支持1024个条件,有时候需要反思,如果业务上有这么多入参条件是否合理


# must 在数组里面2个字段是and的关系

GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  # query 是DSL的入口
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "Dest":"Warsaw"
          }
        },
        {
          "match": {
            "DestWeather": "Rain"
          }
        }
      ]
    }
  }
}

# should 满足任意一个即可,等同于or,注意观察第二个查询total是增加的

GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  "query":{
    "bool": {
      "should": [
        {
          "match": {
            "Dest":"Warsaw"
          }
        }
      ]
    }
  }
}
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  "query":{
    "bool": {
      "should": [
        {
          "match": {
            "Dest":"Warsaw"
          }
        },
        {
          "match": {
            "DestWeather": "Rain"
          }
        }
      ]
    }
  }
}

# filter,类同于must,不过不计算分值,效率比must高,背后采用RaoringBitmap算法高效查询检索
# 这个使用是最多的,一般用来解决mysql的查询瓶颈
# 主要掌握这个就可以了!!!

GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  "query":{
    "bool": {
      "filter": [
        {
          "match": {
            "Dest":"Warsaw"
          }
        },
        {
          "match": {
            "DestWeather": "Rain"
          }
        }
      ]
    }
  }
}

# must_not 与must相反,反向选择不符合条件的结果

GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  "query":{
    "bool": {
      "must_not": [
        {
          "match": {
            "Dest":"Warsaw"
          }
        },
        {
          "match": {
            "DestWeather": "Rain"
          }
        }
      ]
    }
  }
}

# mixed 混合,水平组合,es可以说为每种字段类型都定义了查询语法
# 不同于mysql的索引,查询条件的先后不会影响查询结果和效率

GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "Dest": "Genoa"
          }
        }
      ], 
      "must_not": [
        {
          "match": {
            "Dest":"Warsaw"
          }
        },
        {
          "match": {
            "DestWeather": "Rain"
          }
        }
      ]
    }
  }
}

# mixed 混合,嵌套组合,类同Mysgl 多个括号组合条件
# 可以一直嵌套,但是不推荐,不利于解析和阅读

GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "Dest": "Genoa"
          }
        },
        {
          "bool": {
            "must_not": [
              {
                "match": {
                  "DestWeather": "Sunny"
                }
              }
            ]
          }
        }
      ]
    }
  }
}

## boost 加权组合查询,需要深度学习,这里为入门,适用于text字段
## 给部分字段增加分值权重,以此来影响分词查询排序
## ES 查询默认排序,采取的是依据关键字的关联度计算分值,默认算法是 BM25,多个字段查询时,可以跟不同的字段设定不同的权重,来调整排序。
# 权重组合应用
# 正向加权,就是增加此字段的权重,一般为正值
# 反向加权,就是降低此字段的权重,一般为小于1或者负值
# boosting,关键字
# positive,关键字,正向
# negative,关键字,反向
# negative_boost,关键字,用于降低反向加权的权重比值,取值范围 0~1之间
# boost,关键字,查询时使用,默认1,设置字段分值比重

# 查询1,标准分值
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  "query":{
    "bool": {
      "must_not": [
        {
          "match": {
            "Dest":"Warsaw"
          }
        },
        {
          "match": {
            "DestWeather": "Rain"
          }
        }
      ]
    }
  }
}
# 查询2,negative_boost=0
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "Dest": "Warsaw"
        }
      },
      "negative": {
        "match": {
          "DestWeather": "Rain"
        }
      },
      "negative_boost": 0
    }
  }
}
# 查询3,negative_boost=2
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "Dest": "Warsaw"
        }
      },
      "negative": {
        "match": {
          "DestWeather": "Rain"
        }
      },
      "negative_boost": 2
    }
  }
}
# 查询4,negative_boost=0.5
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits":true,
  "query":{
    "bool": {
      "must": [
        {
          "match": {
            "Dest": "Genoa"
          }
        },
        {
          "bool": {
            "must_not": [
              {
                "match": {
                  "DestWeather": {
                    "query": "Sunny",
                    "boost": 0.2  // 使用 negative_boost 降低不包含 "Sunny" 标签的文档的得分
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}
# 7.0版本以上不支持,静态加权方式,创建mapping时设置
DELETE device-001
PUT device-001
{
  "settings": {
    "refresh_interval": "15s",
    "number_of_shards": 1
  },
  "mappings": {
    "properties": {
      "devId": {
        "type": "keyword"
      },
      "devName": {
        "type": "text",
        "boost": 2
      },
      "devNameExt": {
        "type": "text",
        "boost": 0.2
      }
    }
  }
}

## constant:固定分值
## 多字段组合查询,数据排序依赖很多字段共同的分值,有些不必要的字段,可以设定一个固定值,仅仅用来作为过滤条件,防止过度干预排序分值计算,从而影响排序
## 依赖filter查询模式

GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "constant_score": {
      "filter": {
        "match": {
          "Dest": "Warsaw"
        }
      },
      "boost": 1.2
    }
  }
}

## disiunction 最大分值多条件查询中,提取其中分值最高的,作为影响数据排序的因子
## 应用领域
## 多字段查询检索领域,有很多字段可以同时作为检索条件,但排序时,只要运用其中分值最高的那个用来排序即可,比如电商"商品标题"与"商品简要描述"
## dis_max 查询
## dis_max,关键字,最大值查询入口
## tie_breaker,关键字,最大分值增加分值,在原有的基础之上增加 多少,百分比,取值范围 0~1,默认 0.0
## boost,关键字,最大分值乘以权重,直接在原有分值上乘以权重值,默认 1=100%
## queries,关键字,组合多个查询条件,注意是should 关系

GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "dis_max": {
      "tie_breaker": 0,
      "boost": 1,
      "queries": [
        {
          "term": {
            "DestCountry.keyword": {
              "value": "GB"
            }
          }
        },
        {
          "match": {
            "Dest": "London"
          }
        }
      ]
    }
  }
}

## Function函数组合
# 函数组合查询是 ES中最灵活的,也是最复杂的,同样功能型上也是提高了很多机制
# 查询原理:函数组合,是基于查询后的结果,在结果集上做二次打分,与之前组合查询不一样
# 先初步了解这种方法

# 查询模式
# Function:定义多个查询打分块
# Script_score:脚本定义分值计算规则
# weight:权重占比打分规则
# random:随机自动生成规则
# Field_value_factor:字段值因子
# gauss:高级函数等

# function score
# function_score,关键字,函数查询入口
# query,限制查询数据结果
# 查询航班案例数据,比对 function score 与之前的查询分值数值

# 普通查询
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "term": {
      "DestCountry.keyword": {
        "value": "GB"
      }
    }
  }
}
# 入门查询1,限制查询范围
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "function_score": {
      "query": {
        "term": {
          "DestCountry.keyword": {
            "value": "GB"
          }
        }
      }
    }
  }
}

# functions 多函数组合
# 组合多个 function 自定义查询,基于多个function 组合分值,自定义计算分值逻辑
# function_score,关键字,函数查询入口
# functions,关键字,多个函数组合
# weight,每个函数占比权重
# boost_mode,多函数组合分值计算规则,默认是multiply,相乘
# score_mode,多函数组合分值计算规则,默认是multiply,相乘

# score_mode 取值,多函数组合分值计算规则,默认是 multiply
# 取值         说明
# multiply     所有独立 function 计算后的分值相乘
# Sum          所有独立 function 计算后的分值汇总
# avg          所有独立 function 计算后的分值均值
# first        所有独立 function 计算后的分值选择第一个
# max          所有独立 function 计算后的分值最大值
# min          所有独立 function 计算后的分值最小值

# boost_mode 取值
# 取值         说明
# multiply     所有独立 function 计算后的分值相乘
# Sum          所有独立 function 计算后的分值汇总
# avg          所有独立 function 计算后的分值均值
# first        所有独立 function 计算后的分值选择第一个
# max          所有独立 function 计算后的分值最大值
# min          所有独立 function 计算后的分值最小值

# 查询航班案例数据,对比前后 functions 条件查询分值数据
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "function_score": {
      "query": {
        "term": {
          "DestCountry.keyword":"GB"
        }
      },
      "boost": 1,
      "functions": [
        {
          "filter": {
            "match":{
              "Dest":"Manchester"
            }
          },
          "weight": 1
        },
        {
           "filter": {
            "match":{
              "Origin":"London"
            }
          },
          "weight": 2
        }
      ],
      "max_boost": 10,
      "score_mode": "min",
      "boost_mode": "multiply",
      "min_score": 5
    }
  }
}

# script_score 脚本组合
# 自定义分值计算逻辑,替代默认的 BM25 算法等
# script score,关键字,脚本函数
# script,脚本语法,默认 painless
# boost_mode,分值计算方式,默认multiply=相乘,此处设置sum,加权值
# score_mode,分值计算方式,默认multiply=相乘
# 查询航班案例数据,对比前后查询分值数据,对比数据排序

# 查询1,基于数据字段值打分
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "function_score": {
      "query": {
        "term": {
          "DestCountry.keyword": "GB"
        }
      },
      "script_score": {
        "script": "doc['FlightDelayMin'].value"
      },
      "score_mode": "multiply",
      "boost_mode": "sum"
    }
  }
}
# 查询2,集成数学函数,Math.log
GET kibana_sample_data_flights_reindex/_search
{
  "track_total_hits": true,
  "query": {
    "function_score": {
      "query": {
        "term": {
          "DestCountry.keyword": "GB"
        }
      },
      "script_score": {
        "script": "Math.log(1+doc['FlightDelayMin'].value)"
      },
      "score_mode": "multiply",
      "boost_mode": "sum"
    }
  }
}

## Range 应用
# Range 范围类型,是ES数据类型很大的创新,相比传统数据库,性能优势非常明显,高达几个数量级,内部采用BDK树算法检索。有很多应用场景,比如衣服尺寸,设计时都是按照一个范围值设计的,适合 175~185 身高范围等。

# 范围类型
# 类型名称           类型说明
# integer_range      整数范围数值类型 
# float_range        单精度范围数值类型
# long_range         日期范围类型
# double_range       应用于IP地址范围检索
# date_range         注意日期格式 format
# ip_range           注意ip查询时,语法规则必须符合规范

# 逻辑关系
# 关键字   说明
# gte      填充数据时,数据的起始值包括值本身,类同Mysql 中的大于等于 
# gt       数据起始值,不包括值本身
# lte      填充数据时,数据的结尾值,包括值本身,类同Mysql 中的小于等于 
# lt       数据结尾值,不包括值本身
# relation 查询时,范围计算的关系模式,必须是range字段才有效,关系值:WITHIN=包含, CONTAINS=反包含,INTERSECTS=交叉(默认)

# 创建索引,设置range字段,对比前后查询结果
DELETE device-001
PUT device-001
{
  "mappings": {
    "properties": {
      "devId": {
        "type": "keyword"
      },
      "in_voltage": {
        "type": "integer_range"
      },
      "out_voltage": {
        "type": "integer"
      }
    }
  }
}
PUT device-001/_doc/1
{
  "devId":"001",
  "in_voltage":{
    "gte":100,
    "lte":200
  },
  "out_voltage": 100
}
PUT device-001/_doc/2
{
  "devId":"002",
  "in_voltage":{
    "gte":200,
    "lte":300
  },
  "out_voltage": 200
}
PUT device-001/_doc/3
{
  "devId":"003",
  "in_voltage":{
    "gte":300,
    "lte":400
  },
  "out_voltage": 200
}
GET device-001/_search
{}
# 查询1,默认关系,INTERSECTS 交叉
GET device-001/_search
{
  "query":{
    "range": {
      "in_voltage": {
        "gte": 150,
        "lte": 250,
        "relation":"INTERSECTS"
      }
    }
  }
}
# 查询2,包含
GET device-001/_search
{
  "query":{
    "range": {
      "in_voltage": {
        "gte": 150,
        "lte": 350,
        "relation":"WITHIN"
      }
    }
  }
}
# 查询3,反包含
GET device-001/_search
{
  "query":{
    "range": {
      "in_voltage": {
        "gte": 150,
        "lte": 350,
        "relation":"CONTAINS"
      }
    }
  }
}

# 单数值类型
# 单数值类型,在设置时,仅需要一个值,后续查询可以采用范围查询
# range,关键字来,查询语法,包括范围 gte,lte
# relation,关键字,查询时关系类型,默认交叉,与range类型一样

GET device-001/_search
{
  "query":{
    "range": {
      "out_voltage": {
        "gte": 50,
        "lte": 150
      }
    }
  }
}

## Join父子关系查询
# join,字段“类型关键字
# relations,关系关键字
# routing ,路由保证父子数据在同一分片中
# 场景:假设公司的基本信息,一个公司会有多个子公司,子公司下属又有子公司

DELETE company-001
# 创建join类型字段索引
PUT company-001
{
  "mappings": {
    "properties": {
      "companyId": {
        "type": "keyword"
      },
      "companyName": {
        "type": "keyword"
      },
      "join_father_child": {
        "type": "join",
        "relations": {
          "father": "child"
        }
      }
    }
  }
}
PUT company-001/_doc/1
{
  "companyId":"001",
  "companyName":"集团总公司",
  "join_father_child":"father"
}
PUT company-001/_doc/2?routing=1
{
  "companyId":"002",
  "companyName":"浙江分公司",
  "join_father_child":{
    "name":"child",
    "parent":"1"
  }
}
PUT company-001/_doc/3?routing=1
{
  "companyId":"003",
  "companyName":"武汉分公司",
  "join_father_child":{
    "name":"child",
    "parent":"1"
  }
}
# 查询分为子查询和父查询,关键字:parent_id,has_parent,has_child
# 依据父id查询所有子节点
GET company-001/_search
{
  "query":{
    "parent_id":{
      "type":"child",
      "id":1
    }
  }
}
# 查询有子节点的父节点数据
GET company-001/_search
{
  "query":{
    "has_child":{
      "type":"child",
      "query":{
        "match_all": {}
      }
    }
  }
}
# 查询有父节点的子节点数据
GET company-001/_search
{
  "query":{
    "has_parent":{
      "parent_type":"father",
      "query":{
        "match_all": {}
      }
    }
  }
}

## Nested 嵌套关系
# ES 支持数组类型,但数组类型在查询时,如果是键值对需求,则会出现查询误差,这是由内部实现决定的,为此ES 推出了 nested 嵌套键值对类型
# nested,字段类型关键字
# 场景:假设一个公司有很多区域信息,每一组都是一个键值对,包括省份与城市,运用 nested 类型,在 area字段下增加 type=nested,查询语法中增加 nested 标记

DELETE company-001
# 创建nested类型字段索引
PUT company-001
{
  "mappings":{
    "properties":{
      "companyId":{
        "type":"keyword"
      },
      "companyName":{
        "type":"keyword"
      },
      "area":{
        "type":"nested",
        "properties":{
          "province":{
            "type":"keyword"
          },
          "city":{
            "type":"keyword"
          }
        }
      }
    }
  }
}
# 设置数据
PUT company-001/_doc/1
{
  "companyId": "001",
  "companyName": "零食铺",
  "area": [
    {
      "province": "zj",
      "city": "hz"
    },
    {
      "province": "hb",
      "city": "wh"
    }
  ]
}
# 查询数据,无结果
GET company-001/_search
{
  "query":{
    "nested": {
      "path": "area",
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "area.province": {
                  "value": "zj"
                }
              }
            },
            {
              "term": {
                "area.city": {
                  "value": "wh"
                }
              }
            }
          ]
        }
      }
    }
  }
}
# 查询数据,有结果
GET company-001/_search
{
  "query":{
    "nested": {
      "path": "area",
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "area.province": {
                  "value": "zj"
                }
              }
            },
            {
              "term": {
                "area.city": {
                  "value": "hz"
                }
              }
            }
          ]
        }
      }
    }
  }
}

### 组合查询限制条件与设置
## indices.query.bool.max clause_count
## 索引查询条件,单次最多组合条件查询限制默认1024个,超过会报错
## 此设置属于静态设置,需要在节点启动前设置,且集群中所有节点必须设置为一样
## 在节点 elasticsearch.yml 文件中设置
## indices.query.bool.max clause_count: 1024


### 组合查询建议
## Bool组合优先filter,满足绝大多数场景
## 组合查询优先bool组合条件,其他的都是特定领域,需要再深入研究
## 性能上慎重使用function组合,脚本有性能问题

## 文档地址
# compound 组合查询
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/compound-queries.html
# function score 函数查询
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/query-dsl-function-score-query.html
# range 范围查询
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/range.html
# join 关联查询
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/joining-queries.html
# search-setting 查询条件数量限制
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/search-settings.html
# boost 字段属性
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/mapping-boost.html
 


http://www.kler.cn/a/430090.html

相关文章:

  • gesp(C++四级)(11)洛谷:B4005:[GESP202406 四级] 黑白方块
  • Android基于回调的事件处理
  • OpenPCDet从环境配置到模型训练
  • 计算机网络之---传输层的功能
  • 12_Redis发布订阅
  • List详解 - 双向链表的操作
  • mvn test 失败,单独运行单元测试成功
  • Mysql | 尚硅谷 | 第04章_运算符
  • RabbitMQ 实现分组消费满足服务器集群部署
  • SpringCloud提供的多维度解决方案:构建高效微服务生态系统
  • QT 12月5日练习
  • 11.12[CQU JAVEE_EXP3][JAVA WEB]3h速成JAVA WEB;DE启动Tomcat的各种BUG;GIT
  • 设计模式 在PLM系统的应用场景介绍
  • E卷-计算网络信号200分
  • Linux:Ext系列文件系统
  • 微信小程序uni-app+vue3实现局部上下拉刷新和scroll-view动态高度计算
  • 深度学习(2)前向传播与反向传播
  • Python爬虫——猫眼电影
  • Linux setfacl lsattr chattr 命令详解
  • 什么是 k8s CNI ?
  • 研究生第一篇文献综述怎么写,文献检索,文章整理,文献归纳高效方法小技巧【学习笔记】
  • 解决view-ui-plus 中表单验证不通过问题,select 组件开启multiple模式 总是提示错误,即使不验证也提示,有值也验证失败
  • 亚马逊云科技re:Invent大会:数据与AI如何颠覆企业未来?
  • Tr0ll: 1 Vulnhub靶机渗透笔记
  • 阿里内部正式开源“Spring Cloud Alibaba (全彩小册)”
  • Android问题记录 - Inconsistent JVM-target compatibility detected for tasks