• ES 搜索引擎


    查询文档

    基本语法

    GET /索引库名/_search
    {
        "query":{
            "查询类型":{
                "查询条件":"查询条件值"
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里的query代表一个查询对象,里面可以有不同的查询属性,ES提供了基于JSON的DSL来定义查询。常见的查询类型包括:

    • 查询所有:查询出所有数据,一般测试用。例如:match_all
    • 全文检索:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:match_query、multi_match_query
    • 精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:term、range
    • 地理查询:根据经纬度查询。例如:geo_distance、geo_bounding_box
    • 复合查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:bool、function_score
    #查询所有
    GET /hotel/_search
    {
      "query": {
        "match_all": {}
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    效果:

    {
      "took" : 1, //查询花费时间,单位是毫秒
      "timed_out" : false,  //是否超时
      "_shards" : {  //分片信息
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : { //搜索结果
        "total" : { //搜索到的总条数
          "value" : 201,
          "relation" : "eq"
        },
        "max_score" : 1.0, //所有结果中文档得分的最高分
        "hits" : [ //搜索结果的文档对象数组,每个元素是一条搜索到的文档信息
          {
            "_index" : "hotel",
            "_type" : "_doc",
            "_id" : "36934",
            "_score" : 1.0,
            "_source" : {
              "address" : "静安交通路40号",
              "brand" : "7天酒店",
              "business" : "四川北路商业区",
              "city" : "上海",
              "id" : 36934,
              "location" : "31.251433, 121.47522",
              "name" : "7天连锁酒店(上海宝山路地铁站店)",
              "pic" : "https://m.tuniucdn.com/fb2/t1/G1/M00/3E/40/Cii9EVkyLrKIXo1vAAHgrxo_pUcAALcKQLD688AAeDH564_w200_h200_c1_t0.jpg",
              "price" : 336,
              "score" : 37,
              "starName" : "二钻"
            }
          },
            //省略..........
        ]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    全文检索

    • 对用户搜索的内容做分词,得到词条
    • 根据词条去倒排索引库中匹配,得到文档id
    • 根据文档id找到文档,返回给用户

    match

    match查询:全文检索查询的一种,会对用户输入内容分词,然后去倒排索引库检索,语法:

    #match 倒排索引库查询
    GET /hotel/_search
    {
      "query": {
        "match": {
          "all": "外滩如家"
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    效果:

    {
      "took" : 3,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 32,
          "relation" : "eq"
        },
        "max_score" : 5.920452,
        "hits" : [
          {
            "_index" : "hotel",
            "_type" : "_doc",
            "_id" : "434082",
            "_score" : 5.920452,
            "_source" : {
              "address" : "复兴东路260号",
              "brand" : "如家",
              "business" : "豫园地区",
              "city" : "上海",
              "id" : 434082,
              "location" : "31.220706, 121.498769",
              "name" : "如家酒店·neo(上海外滩城隍庙小南门地铁站店)",
              "pic" : "https://m.tuniucdn.com/fb2/t1/G6/M00/52/B6/Cii-U13eXLGIdHFzAAIG-5cEwDEAAGRfQNNIV0AAgcT627_w200_h200_c1_t0.jpg",
              "price" : 392,
              "score" : 44,
              "starName" : "二钻"
            }
          },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    multi_match

    multi_match:与match查询类似,只不过允许同时查询多个字段,
    语法:

    GET /hotel/_search
    {
      "query": {
        "multi_match": {
          "query": "",
          "fields": ["field1","field2"]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    示例:

    GET /hotel/_search
    {
      "query": {
        "multi_match": {
          "query": "外滩如家",
          "fields": ["name","business","brand"]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    效果:

    {
      "took" : 9,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 32,
          "relation" : "eq"
        },
        "max_score" : 4.620212,
        "hits" : [
          {
            "_index" : "hotel",
            "_type" : "_doc",
            "_id" : "434082",
            "_score" : 4.620212,
            "_source" : {
              "address" : "复兴东路260号",
              "brand" : "如家",
              "business" : "豫园地区",
              "city" : "上海",
              "id" : 434082,
              "location" : "31.220706, 121.498769",
              "name" : "如家酒店·neo(上海外滩城隍庙小南门地铁站店)",
              "pic" : "https://m.tuniucdn.com/fb2/t1/G6/M00/52/B6/Cii-U13eXLGIdHFzAAIG-5cEwDEAAGRfQNNIV0AAgcT627_w200_h200_c1_t0.jpg",
              "price" : 392,
              "score" : 44,
              "starName" : "二钻"
            }
          },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    可以看到,match和multi_match两种查询结果是一样的是因为我们将brand、name、business值都利用copy_to复制到了all字段中,虽然效果一样但是 搜索字段越多,对查询性能影响越大,因此建议采用copy_to,然后单字段查询的方式。

    精准查询

    精确查询一般是查找keyword、数值、日期、boolean等类型字段,它不会对搜索条件分词。常见的有:

    • term:根据词条精确匹配,一般搜索keyword类型、数值类型、布尔类型、日期类型字段
    • range:根据数值范围查询,可以是数值、日期的范围

    term

    term: 根据词条进行精确查询,查询过程中不会对词条进行分词处理
    语法:

    #精确查询
    GET /hotel/_search
    {
      "query": {
        "term": {
          "FIELD": {
            "value": "VALUE"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    示例:

    GET /hotel/_search
    {
      "query": {
        "term": {
          "city": {
            "value": "北京"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    range

    范围查找
    语法:

    GET /indexName/_search
    {
      "query": {
        "range": {
          "FIELD": {
            "gte": 10, // 这里的gte代表大于等于,gt则代表大于
            "lte": 20 // lte代表小于等于,lt则代表小于
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    示例:

    GET /hotel/_search
    {
      "query": {
        "range": {
          "price": {
            "gte": 1000,
            "lte": 2000
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    地理查询

    应用场景:根据经纬度查询常见场景包括:
    携程:搜索附近的九点
    滴滴:搜索附近的出租车

    geo_bounding_box 矩形范围

    矩形范围查询,也就是geo_bounding_box查询,查询坐标落在某个矩形范围的所有文档

    查询时,需要指定矩形的左上右下两个点的坐标,然后画出一个矩形,落在该矩形内的都是符合条件的点。
    在这里插入图片描述

    获取坐标请点击这里!

    语法:

    {
      "query": {
        "geo_bounding_box": {
          "location": {
          "top_left": {//左上坐标
            "lat": 40.08,
            "lon": 116.47
          },
          "bottom_right": {//右下坐标
            "lat":39.9,
            "lon":116.405
            }
          }
        }
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    geo_distance 圆形范围

    附近查询,也叫做距离查询(geo_distance):查询到指定中心点小于某个距离值的所有文档。

    也就是说在地图上找一个点作为圆心,以指定距离为半径,画一个圆,落在圆内的坐标都算符合条件
    在这里插入图片描述
    语法:

    GET /hotel/_search
    {
      "query": {
        "geo_distance":{
          "distance":"15km", // 半径
          "location":"39.9,116.405" // 圆心 这个坐标是天安门
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    fuction_score 算分函数

    fuction_score:算分函数查询,可以控制文档相关性算分,控制文档排名
    当我们利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列

    例如,我们搜索 "虹桥如家",结果如下:
    在这里插入图片描述
    elasticsearch会根据词条和文档的相关度做打分,算法由两种:

    • TF-IDF算法
    • BM25算法,elasticsearch5.1版本后采用的算法

    算分函数查询

    在这里插入图片描述
    算分函数关键点是:

    • 过滤条件:决定哪些文档的算分被修改
    • 算分函数:决定函数算分的算法
    • 运算模式:决定最终算分结果
      示例:
    # 默认查询
    GET /hotel/_search
    {
      "query": {
        "match": {
          "all": "北京"
        }
      }
    }
    
    # 算法函数查询
    GET /hotel/_search
    {
      "query": {
        "function_score": {
          "query": {
            "match": {
              "all": "北京"
            }
          },
          "functions": [
            {
              "filter": {
                "term": {
                  "brand": "凯悦"
                }
              },
              "weight": 10
            }
          ],
          "boost_mode": "multiply"
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    bool query 复合查询

    bool query:复合查询,也称为布尔查询,它可以利用多种逻辑关系将多个查询条件组装在一起,然后实现复杂搜索
    布尔查询是一个或多个查询子句的组合,每一个子句就是一个子查询。子查询的组合方式有:

    • must:必须匹配每个子查询,类似“与” and

    • should:选择性匹配子查询,类似“或” or

    • must_not:必须不匹配,不参与算分,类似“非” not

    • filter:必须匹配,不参与算分
      搜索时,参与打分的字段越多,查询的性能也越差。因此这种多条件查询时,建议这样做:

    • 搜索框的关键字搜索,是全文检索查询,使用must查询,参与算分

    • 其它过滤条件,采用filter查询。不参与算分

    GET /hotel/_search
    {
      "query": {
        "bool": {
          "must": [
            {"term": {
              "name": {
                "value": "如家"
              }
            }}
          ],
          "must_not": [
            {"range":{
              "price": {
                "gte": 400
              }
            }
            }
          ],
          "filter": [
            {
              "geo_distance": {
                "distance": "10km",
                "location": {
                  "lat": 39.9,
                  "lon":  116.405
                }
              }
            }
          ]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    结果处理

    排序
    elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序。

    可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

    普通字段排序

    语法:

    GET /hotel/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": [
        {   //语法一
          "FIELD": {      //排序字段,排序方式 ASC,DESC
            "order": "desc"
          }
        },
        { //语法二
          "field": "desc" //排序字段,排序方式 ASC,DESC
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    示例:酒店数据按照用户评价(score)降序排序,评价相同的按照价格(price)升序排序

    GET /hotel/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": [
        {
          "score": {
            "order": "desc"
          },
          "price": {
            "order": "asc"
          }
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    地理坐标排序

    语法:

    GET /indexName/_search
    {
      "query": {
        "match_all": {}
      },
      "sort": [
        {
          "_geo_distance" : {
              "FIELD" : "纬度,经度", // 文档中geo_point类型的字段名、目标坐标点
              "order" : "asc" // 排序方式
          }
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    获取经纬度点击这里
    示例:假设我的位置是:31.034661,121.612282,寻找我周围距离最近的酒店。

    GET /hotel/_search
    {
        "query": {
        "match_all": {}
      },
      "sort": [
        {
          "_geo_distance": {
            "location": {
              "lat": 39.909187,
             "lon": 116.397455
            },
            "order": "asc"
          }
        }
      ]
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    分页

    elasticsearch 默认情况下只返回top10的数据。而如果要查询更多数据就需要修改分页参数了。

    elasticsearch中通过修改from、size参数来控制要返回的分页结果:

    • from:从第几个文档开始
    • size:总共查询几个文档
      类似于mysql中的limit ?, ?

    基本分页

    语法:

    GET /hotel/_search
    {
      "query":{
        "match_all":{}
      },
      "from":0, //分页开始的位置,默认为0
      "size":10, //期望获取的文档总数
      "sort":[
        {"price":"asc"}
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    高亮

    ** 基本语法:**

    GET /hotel/_search
    {
      "query": {
        "match": {
          "FIELD": "TEXT"
        }
      },
      "highlight": {
        "fields": {	//指定要高亮的字段
          "FIELD": {
            "pre_tags": "",	//标记高亮字段的前置标签
            "post_tags": ""	//标记高亮字段的后置标签
        }
      }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    示例:

    # 查询字段跟高亮字段一致
    GET /hotel/_search
    {
      "query": {
        "match": {
          "name": "如家"
        }
      },
      "highlight": {
        "fields": {
          "name": {
            "pre_tags": "",
            "post_tags": ""
          }
        }
      }
    }
    
    # 查询字段跟高亮字段不一致
    GET /hotel/_search
    {
      "query": {
        "match": {
          "all": "如家"
        }
      },
      "highlight": {
        "fields": {
          "name": {
            "pre_tags": "",
            "post_tags": "",
            "require_field_match": "false"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    实验1 线性回归 实操项目1——糖尿病情预测
    ruoyi-nbcio增加flowable流程待办消息的提醒,并提供右上角的红字数字提醒(一)
    【Go语言如何用 interface 实现多态】
    视联网拓展乡村振兴新思路
    搞定蓝牙——第二篇(蓝牙架构)
    java-php-python-ssm基于人事管理系统计算机毕业设计
    pytorch TORCH.NN 到底是什么?
    使用 Django Rest Framework 构建强大的 Web API
    unity 点击3D物体
    MacOS Pro笔记本硬盘升级纪实
  • 原文地址:https://blog.csdn.net/apple_69693064/article/details/126804552