ElasticSearch-常用搜索

Posted 肉蟹宝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于ElasticSearch-常用搜索的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch系列---前缀搜索和模糊搜索

Elasticsearch系列---前缀搜索和模糊搜索

elasticSearch精确索引和全文索引

lucene-查询query->TermQuery按词条搜索

[ElasticSearch]Java API 之 词条查询(Term Level Query)

ElasticSearch基本查询