ElasticSearch-常用搜索

全文检索查询

使用场景

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

  • 对用户搜索的内容做分词,得到词条
  • 根据词条去倒排索引库中匹配,得到文档id
  • 根据文档id找到文档,把所有匹配结果以并集或交集返回给用户

比较常见的场景包括:

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

DSL语句

常见的全文检索查询包括:

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

match查询

#搜索单字段
GET /indexName/_search
{
  "query":{
    "match":{
      "字段名称":"TEXT",
      "operator":"or and"   #搜索分词时选择关键字的关系为or 或者 and
    }
  }
}
#搜索全部
GET /indexName/_serach
{
  "query":{
    "match_all":{}
  }
}

multi_match查询

GET /indexName/_search
{
  "query":{
    "mutil_match":{
      "query":"TEXT",
      "field":["FIELD1","FIELD2"]
    }
  }
}

精确查询

使用场景

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

  • term:根据词条精确值查询 equals =
  • range:根据值的范围查询 >= , <=, between and

DSL语句

term查询

// term查询
GET /indexName/_search
{
  "query": {
    "term": {
      "FIELD": {
        "value": "VALUE"
      }	
    }
  }
}

range查询

// range查询
GET /indexName/_search
{
  "query": {
    "range": {
      "FIELD": {
        "gte": 10, // 这里的gte代表大于等于,gt则代表大于
        "lte": 20 // lte代表小于等于,lt则代表小于
      }
    }
  }
}

地理坐标查询

使用场景

所谓的地理坐标查询,就是根据经纬度查询

常见的使用场景包括:

  • 携程:搜索附近的酒店
  • 滴滴:搜索附近的出租车
  • 微信:搜索附近的人

DSL语句

geo_bounding_box查询

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

查询时,需指定左上,右下两个坐标

语法如下:

# 地理位置搜索
GET hotel/_search
{
  "query": {
    "geo_bounding_box":{
      "location":{
        "top_left":{
          "lat":31.1,
          "lon":121.5
        },
        "bottom_right":{
          "lat":30.9,
          "lon":121.7
        }
      }
    }
  }
}

geo_distance查询

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

语法如下:

GET hotel/_search
{
  "query": {
    "geo_distance":{
      "distance":"15km",
      "location":"31.21,121.5"
    }
  }
}

复合查询-布尔查询

使用场景

布尔查询是一个或多个查询子句的组合,每一个子句就是一个子查询。子查询的组合方式有:

  • must:必须匹配每个子查询,类似“与”,must的条件参与算分的
  • should:选择性匹配子查询,类似“或”
  • must_not:必须不匹配,不参与算分,类似“非”
  • filter:效果和must一样,都是and。必须匹配,filter的条件不参与算分

DSL语句

GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {"city": "上海" }}
      ],
      "should": [
        {"term": {"brand": "皇冠假日" }},
        {"term": {"brand": "华美达" }}
      ],
      "must_not": [
        { "range": { "price": { "lte": 500 } }}
      ],
      "filter": [
        { "range": {"score": { "gte": 45 } }}
      ]
    }
  }
}

复合查询-算分函数查询

使用场景

ElasticSearch会根据词条和文档的相关度打分,算法有两种:

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

相关场景:百度搜索打广告的优先展示

DSL语句

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

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

function score的运行流程如下:

  1. 根据原始条件查询搜索文档,并且计算相关性算分,称为原始算分
  2. 根据过滤条件,过滤文档
  3. 符合过滤条件的文档,基于算分函数运算,得到函数算分
  4. 原始算分和函数算分基于运算模式做运算,得到最终结果,作为相关性算分

语法如下:

#  需求: 查询如家酒店, 对于深圳的如家进行+10分
GET hotel/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "all": "如家"
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "city": "深圳"
            }
          },
          "weight": 10
        }
      ],
      "boost_mode": "sum"
    }
  }
}

搜索结果处理

排序

elasticsearch默认是根据相关性算分来排序,但是也支持自定义方式对搜索结果排序,可以排序的字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等

普通字段排序

keyword、数值、日期类型的排序的语法基本一致

语法如下

GET /indexName/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "FIELD": "desc"  // 排序字段、排序方式ASC、DESC
    }
  ]
}

排序条件是一个数组,按照声明的顺序,当第一个条件相等时,再按照第二个条件排序

地理坐标排序

语法如下

GET /indexName/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance" : {
          "FIELD" : "纬度,经度", // 文档中geo_point类型的字段名、目标坐标点
          "order" : "asc", // 排序方式
          "unit" : "km" // 排序的距离单位
      }
    }
  ]
}
  • 指定一个坐标,作为目标点
  • 计算每一个文档中,必须是geo_point类型的坐标到目标点的距离是多少
  • 根据距离排序

分页

elasticsearc默认情况下只返回top10的数据,而如果要查询更多数据就要修改分页参数,elasticsearch中·通过修改from、size参数来控制要返回的分页结果

  • from:从第几个文档开始,从0开始的
  • size:总共查询几个文档

语法如下:

#  查找如家酒店,查找离我最近的如家酒店, 分页
GET hotel/_search
{
  "query": {
    "match": {
      "name": "如家酒店"
    }
  },
  "sort": [
    {
      "_geo_distance": {
        "location": "39.76,116.33",
        "order": "asc",
        "unit": "km"
      }
    }
  ],
  "from": 1,
  "size": 2
}

高亮显示

对关键字高亮处理

语法如下

GET /hotel/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT" // 查询条件,高亮一定要使用全文检索查询
    }
  },
  "highlight": {
    "fields": { // 指定要高亮的字段
      "FIELD": {
        "pre_tags": "<em>",  // 用来标记高亮字段的前置标签 ,默认使用<em>标签
        "post_tags": "</em>" // 用来标记高亮字段的后置标签
      }
    }
  }
}

注意:

  • 高亮是对关键字高亮,因此搜索条件必须带有关键字而不能是范围这样的查询
  • 默认情况下,高亮的字段,必须与搜索的指定的字段一致,否则无法高亮
  • 如果对非搜索字段高亮,则需要添加一个属性:required_filed_match=false

猜你喜欢

转载自blog.csdn.net/qq_45779998/article/details/128304387