• 分布式搜索引擎


    1 DSL查询文档

    elasticsearch的查询依然是基于JSON风格的DSL来实现的。

    1.1.DSL查询分类

    Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括:

    • 查询所有:查询出所有数据,一般测试用。例如:match_all

    • 全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:

      • match_query
      • multi_match_query
    • 精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:

      • ids
      • range
      • term
    • 地理(geo)查询:根据经纬度查询。例如:

      • geo_distance
      • geo_bounding_box
    • 复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:

      • bool
      • function_score

    查询的语法基本一致:

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

    例如查询所有

    • 查询类型为match_all
    • 没有查询条件
    // 查询所有
    GET /indexName/_search
    {
      "query": {
        "match_all": {
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.全文搜索查询

    2.1.使用场景

    全文检索查询的基本流程如下:

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

    比较常用的场景包括:

    • 商城的输入框搜索
    • 百度输入框搜索

    2.2 match和mulit_match查询

    match查询是全文检索查询的一种,会对用户输入内容进行分词,然后进行倒排索引库检索.(单字段查询)

    • match查询:单字段查询
    • multi_match查询:多字段查询,任意一个字段符合条件就算符合查询条件

    match查询语法如下:

    GET /indexName/_search
    {
      "query": {
        "match": {
          "FIELD": "TEXT"
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    mulit_match语法如下:

    GET /indexName/_search
    {
      "query": {
        "multi_match": {
          "query": "TEXT",
          "fields": ["FIELD1", " FIELD12"]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    # 示例
    GET /hotel/_search
    {
      "query": {
        "match": {
          "all": "西直门如家"
        }
      }
    }
    
    GET /hotel/_search
    {
      "query": {
        "multi_match": {
          "query": "外滩如家",
          "fields": ["brand","name"]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    因为我们将brand、name、business值都利用copy_to复制到了all字段中。因此你根据三个字段搜索,和根据all字段搜索效果当然一样了。

    但是,搜索字段越多,对查询性能影响越大,因此建议采用copy_to,然后单字段查询的方式。

    match和multi_match的区别是什么?

    • match:根据一个字段查询
    • multi_match:根据多个字段查询,参与查询字段越多,查询性能越差

    3.精确查询

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

    • term:根据词条精确值查询
    • range:根据值的范围查询

    利用term进行精确查询,精确查询city值为上海的酒店.

    # term查询
    GET /hotel/_search
    {
      "query": {
        "term": {
          "city": {
            "value": "上海"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    利用range进行范围查询查询,查询price在100-300之间的酒店,其中gte表示大于等于,lte表示小于等于(另外还有gtlt分别表示大于和小于).

    # range查询
    GET /hotel/_search
    {
      "query": {
        "range": {
          "price": {
            "gte": 100,
            "lte": 300
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.地理查询

    根据经纬度查询.

    4.1矩形范围查询

    geo_bounding_box:查询geo_point落在某个矩形范围的所有文档.
    在这里插入图片描述

    // geo_bounding_box查询
    GET /indexName/_search
    {
      "query": {
        "geo_bounding_box": {
          "FIELD": {
            "top_left": { // 左上点
              "lat": 31.1,
              "lon": 121.5
            },
            "bottom_right": { // 右下点
              "lat": 30.9,
              "lon": 121.7
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    4.2附近查询

    geo_distance:查询指定中心点小于某个距离值的所有文档.

    // geo_distance 查询
    GET /indexName/_search
    {
      "query": {
        "geo_distance": {
          "distance": "15km", // 半径
          "FIELD": "31.21,121.5" // 圆心
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5.相关算法

    复合(compound)查询:复合查询可以将其它简单查询组合起来,实现更复杂的搜索逻辑。常见的有两种:

    • fuction score:算分函数查询,可以控制文档相关性算分,控制文档排名
    • bool query:布尔查询,利用逻辑关系组合多个其它的查询,实现复杂搜索

    利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。在elasticsearch中,早期使用的打分算法是TF-IDF算法,公式如下:
    在这里插入图片描述

    在后来的5.1版本升级中,elasticsearch将算法改进为BM25算法,公式如下:

    image-20210721190416214

    TF-IDF算法有一各缺陷,就是词条频率越高,文档得分也会越高,单个词条对文档影响较大。而BM25则会让单个词条的算分有一个上限,曲线更加平滑:

    image-20210721190907320

    5 Funciton score query

    通过Funciton score query可以修改文档的相关性算分(query score),根据新的到的算分进行排序.
    在这里插入图片描述

    function score 查询中包含四部分内容:

    • 原始查询条件:query部分,基于这个条件搜索文档,并且基于BM25算法给文档打分,原始算分(query score)
    • 过滤条件:filter部分,符合该条件的文档才会重新算分
    • 算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score),有四种函数
      • weight:函数结果是常量
      • field_value_factor:以文档中的某个字段值作为函数结果
      • random_score:以随机数作为函数结果
      • script_score:自定义算分函数算法
    • 运算模式:算分函数的结果、原始查询的相关性算分,两者之间的运算方式,包括:
      • multiply:相乘
      • replace:用function score替换query score
      • 其它,例如:sum、avg、max、min

    正常查询在外滩的酒店

    GET /hotel/_search
    {
      "query": {
        "function_score": {
          "query": {
            "match": {
              "all": "外滩"
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述
    给如家的酒店进行分数的加权,每个加十分.

    GET /hotel/_search
    {
      "query": {
        "function_score": {
          "query": {
            "match": {
              "all": "外滩"
            }
          },
          "functions": [
            {
              "filter": {
                "term": {
                  "brand": "如家"
                }
              },
              "weight": 10
            }
          ],
          "boost_mode": "sum"
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    6 Boolean Query

    布尔查询是一个或多个查询子句的组合.组合方式有:

    • must:必须匹配每个子查询,类似“与”
    • should:选择性匹配子查询,类似“或”
    • must_not:必须不匹配,不参与算分,类似“非”
    • filter:必须匹配,不参与算分

    查找上海的酒店
    从皇宫假日和如家上选取
    价格不低于500
    评分高于45

    GET /hotel/_search
    {
      "query": {
        "bool": {
          "must": [
            {"term": {"city":"上海"}}
          ],
          "should": [
            {"term": {"brand":"皇宫假日"}},
            {"term": {"brand":"如家"}}
          ],
          "must_not": [
            {"range": {"price":{"lte": 500}}}
          ],
          
          "filter": [
            {"range": {"score":{"gte": 45}}}
          ]
          
        }
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    需求:搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店。

    分析:

    • 名称搜索,属于全文检索查询,应该参与算分。放到must中
    • 价格不高于400,用range查询,属于过滤条件,不参与算分。放到must_not中
    • 周围10km范围内,用geo_distance查询,属于过滤条件,不参与算分。放到filter中
    GET /hotel/_search
    {
      "query": {
        "bool": {
          "must": [
            {"term": {"brand":"如家"}}
          ],
          "must_not": [
            {"range": {"price":{"gte": 400}}}
          ],
          
          
          "filter": [
            {"geo_distance": {
          "distance": "10km", 
          "location": "31.21,121.5" 
            }}
          ]
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    76.【图】
    【图像处理 】003 图片处理工具类
    MediaPlayer_Analyze-1-framework
    leetcode 409 Longest Palindrome 最长回文串(简单)
    JavaScript 30 JavaScript 日期格式
    吃透Redis(四):网络框架篇-多路复用器
    基于Java的大学生兼职论坛管理系统设计与实现(源码+lw+部署文档+讲解等)
    Java skill - 动态指定feign的访问地址
    【BI报表】Superset二开相关接口文档
    CMake
  • 原文地址:https://blog.csdn.net/qq_41296039/article/details/132604590