第四章 搜索功能

这篇具有很好参考价值的文章主要介绍了第四章 搜索功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 基本搜索

  1. 指定返回的字段

在ES中,通过_source子句可以设定返回结果的字段。_source指向一个JSON数组,数组中的元素是希望返回的字段名称。

  • 例如,通过source指定查询字段
GET /hotol/_search
{
  "_source": ["title","price"]
}
  1. 结果计数

给前端传递搜索匹配结果的文档条数,即需要对搜索结果进行计数。ES提供了_count API功能,在该API中,用户提供query子句用于结果匹配,ES会返回匹配的文档条数。

GET /hotol/_count
  1. 结果分页
GET /hotol/_search
{
  "from": 0,# 起始页码
  "size": 20 # 当前页面显示记录数
}

在默认情况下,用户最多可以取得10 000个文档,即from为0时,size参数最大为10 000,如果请求超过该值,ES返回报错; 如果确实需要返回多于10 000条的数据,可以适当修改max_result_window的值。

PUT /hotol/_settings
{
  "index":{
    "max_result_window":20000
  }
}

作为一个分布式搜索引擎,一个ES索引的数据分布在多个分片中,而这些分片又分配在不同的节点上。一个带有分页的搜索请求往往会跨越多个分片,每个分片必须在内存中构建一个长度为from+size的、按照得分排序的有序队列,用以存储命中的文档。然后这些分片对应的队列数据都会传递给协调节点,协调节点将各个队列的数据进行汇总,需要提供一个长度为number_of_shards*(from+size)的队列用以进行全局排序,然后再按照用户的请求从from位置开始查找,找到size个文档后进行返回。 ES不适合深翻页。什么是深翻页呢?简而言之就是请求的from值很大; 当深翻页的请求过多时会增加各个分片所在节点的内存和CPU消耗。尤其是协调节点,随着页码的增加和并发请求的增多,该节点需要对这些请求涉及的分片数据进行汇总和排序,过多的数据会导致协调节点资源耗尽而停止服务。 作为搜索引擎,ES更适合的场景是对数据进行搜索,而不是进行大规模的数据遍历。一般情况下,只需要返回前1000条数据即可,没有必要取到10 000条数据。如果确实有大规模数据遍历的需求,可以参考使用scroll模式或者考虑使用其他的存储引擎。

  1. 性能分析

ES提供了profile功能,该功能详细地列出了搜索时每一个步骤的耗时,可以帮助用户对DSL的性能进行剖析。开启profile功能只需要在一个正常的搜索请求的DSL中添加"profile":"true"即可。

GET /hotol/_search
{
  "profile": true
}

一个搜索可能会跨越多个分片,所以使用shards数组放在profile子句中。每个shard子句中包含3个元素,分别是id、searches和aggregations。

  1. id表示分片的唯一标识,它的组成形式为[nodeID][indexName][shardID]
  2. searches以数组的形式存在,因为有的搜索请求会跨多个索引进行搜索。每一个search子元素即为在同一个索引中的子查询
  3. aggregations只有在进行聚合运算时才有内容
  1. 评分分析

在使用搜索引擎时,一般都会涉及排序功能。如果用户不指定按照某个字段进行升序或者降序排列,那么ES会使用自己的打分算法对文档进行排序。有时我们需要知道某个文档具体的打分详情,以便于对搜索DSL问题展开排查。ES提供了explain功能来帮助使用者查看搜索时的匹配详情

GET /hotol/_explain/001
{
  "query": {
    "term": {
      "city": {
        "value": "长春"
      }
    }
  }
}

2 搜索匹配功能

2.1 查询所有文档

使用match_all查询文档时,ES不对文档进行打分计算,默认情况下给每个文档赋予1.0的得分。用户可以通过boost参数设定该分值。

GET /hotol/_search
{
  "query": {
    "match_all": {
      "boost": 1 
    }
  }
}

2.2 term级别查询

  1. term查询

term查询是结构化精准查询的主要查询方式,用于查询待查字段和查询值是否完全匹配

GET /hotol/_search
{
  "query": {
    "term": {
      "price": 680.00
    }
  }
}
  1. terms查询

terms查询是term查询的扩展形式,用于查询一个或多个值与待查字段是否完全匹配

GET /hotol/_search
{
  "query": {
    "terms": {
      "city": ["长春","沈阳"]
    }
  }
}
  1. range查询

range查询用于范围查询,一般是对数值型和日期型数据的查询。使用range进行范围查询时,用户可以按照需求中是否包含边界数值进行选项设置,可供组合的选项如下: gt:大于;·lt:小于;·gte:大于或等于;·lte:小于或等于。

  1. exists查询

可以用exists搜索。字段不为空的条件有:·值存在且不是null;·值不是空数组;·值是数组,但不是[null]。

GET /hotol/_search
{
  "query": {
    "exists": {
      "field": "city"
    }
  }
}

2.3 布尔查询

布尔查询是常用的复合查询,它把多个子查询组合成一个布尔表达式,这些子查询之间的逻辑关系是“与”,即所有子查询的结果都为true时布尔查询的结果才为真。布尔查询还可以按照各个子查询的具体匹配程度对文档进行打分计算

  1. must查询

当查询中包含must查询时,相当于逻辑查询中的“与”查询。命中的文档必须匹配该子查询的结果,并且ES会将该子查询与文档的匹配程度值加入总得分里。must搜索包含一个数组,可以把其他的term级别的查询及布尔查询放入其中。

GET /hotol/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "city": {
              "value": "长春"
            }
          }
        },
        {
          "range": {
            "price": {
              "gte": 500,
              "lte": 1000
            }
          }
        }
      ]
    }
  }
}
  1. should查询

当查询中包含should查询时,表示当前查询为“或”查询。命中的文档可以匹配该查询中的一个或多个子查询的结果,并且ES会将该查询与文档的匹配程度加入总得分里。should查询包含一个数组,可以把其他的term级别的查询及布尔查询放入其中。

GET /hotol/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "city": {
              "value": "长春"
            }
          }
        },
        {
          "range": {
            "price": {
              "gte": 500,
              "lte": 1000
            }
          }
        }
      ]
    }
  }
}
  1. must not查询

当查询中包含must not查询时,表示当前查询为“非”查询。命中的文档不能匹配该查询中的一个或多个子查询的结果,ES会将该查询与文档的匹配程度加入总得分里。must not查询包含一个数组,可以把其他term级别的查询及布尔查询放入其中。

GET /hotol/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "term": {
            "city": {
              "value": "长春"
            }
          }
        },
        {
          "range": {
            "price": {
              "gte": 500,
              "lte": 1000
            }
          }
        }
      ]
    }
  }
}

2.4 filter查询

filter查询即过滤查询,该查询是布尔查询里非常独特的一种查询。其他布尔查询关注的是查询条件和文档的匹配程度,并按照匹配程度进行打分;而filter查询关注的是查询条件和文档是否匹配,不进行相关的打分计算,但是会对部分匹配结果进行缓存。

GET /hotol/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "city": {
              "value": "长春"
            }
          }
        },
        {
          "range": {
            "price": {
              "gte": 500,
              "lte": 1000
            }
          }
        }
      ]
    }
  }
}

2.5 Constant Score查询

如果不想让检索词频率TF(Term Frequency)对搜索结果排序有影响,只想过滤某个文本字段是否包含某个词,可以使用Constant Score将查询语句包装起来

GET /hotol/_search
{
  "_source": ["title"], 
  "query": {
    "constant_score": {
      "filter": {
        "match":{
          "title":"富豪"
        }
      },
      "boost": 1.2
    }
  }
}

2.6 function score查询

当使用ES进行搜索时,命中的文档默认按照相关度进行排序。有些场景下用户需要干预该“相关度”,此时就可以使用Function Score查询。使用时,用户必须定义一个查询以及一个或多个函数,这些函数为每个文档计算一个新分数

GET /hotol/_search
{
  "_source": ["title"], 
  "query": {
    "function_score": {
      "query": {
        "match":{
          "title":"富豪"
        }
      },
      "functions": [
         {
           "random_score": {}
         }
      ],
      "score_mode": "sum"
    }
  }
}

2.7 全文查询

不同于结构化查询,全文搜索首先对查询词进行分析,然后根据查询词的分词结果构建查询。这里所说的全文指的是文本类型数据(text类型),默认的数据形式是人类的自然语言,如对话内容、图书名称、商品介绍和酒店名称等。结构化搜索关注的是数据是否匹配,全文搜索关注的是匹配的程度;结构化搜索一般用于精确匹配,而全文搜索用于部分匹配。

  1. match查询

match查询是全文搜索的主要代表。对于最基本的math搜索来说,只要分词中的一个或者多个在文档中存在即可。

#默认情况下,match查询使用的是标准分词器,中文按单个文字拆分匹配
GET /hotol/_search
{
  "_source": ["title"], 
  "query": {
    "match": {
      "title": "大富豪店"
    }
  }
}
  • 设置查询词之间的匹配结果为“与”关系
GET /hotol/_search
{
  "_source": ["title"], 
  "query": {
    "match": {
      "title": {
        "query": "大富豪店",
        "operator": "and"
      }
    }
  }
}
  • 采用minimum_should_match参数,该参数叫作最小匹配参数,其值为一个数值,意义为可以匹配上的词的个数。在一般情况下将其设置为一个百分数,因为在真实场景中并不能精确控制具体的匹配数量。以下示例设置最小匹配为80%的文档
GET /hotol/_search
{
  "_source": ["title"], 
  "query": {
    "match": {
      "title": {
        "query": "大富豪店",
        "operator": "and",
        "minimum_should_match": "80%"
      }
    }
  }
}
  1. multi_match查询

用户需要在多个字段中查询关键词,除了使用布尔查询封装多个match查询之外,可替代的方案是使用multi_match。可以在multi_match的query子句中组织数据匹配规则,并在fields子句中指定需要搜索的字段列表。

  • 搜索这个两个字段是否包含“店”
GET /hotol/_search
{
  "_source": ["title"], 
  "query": {
    "multi_match": {
      "query": "店",
      "fields": ["title","city"]
    }
  }
}
  1. match_phrase查询

match_phrase用于匹配短语,与match查询不同的是,match_phrase用于搜索确切的短语或邻近的词语。

GET /hotol/_search
{
  "query": {
    "match_phrase": {
      "title": "酒店富豪"
    }
  }
}

2.8 基于地理位置查询

ES为用户提供了基于地理位置的搜索功能。它主要支持两种类型的地理查询:一种是地理点(geo_point),即经纬度查询,另一种是地理形状查询(geo_shape),即支持点、线、圆形和多边形查询等。 geo_point字段类型的查询方式有3种,分别为geo_distance查询、geo_bounding_box查询和geo_polygon。

  1. geo_distance查询方式 geo_distance查询方式需要用户指定一个坐标点,在指定距离该点的范围后,ES即可查询到相应的文档。假设北京天安门的经纬度为[116.4039,39.915143],以下为使用geo_distance查询所找到的天安门5km范围内的酒店
GET /hotol/_search
{
  "query": {
    "geo_distance": {
      "distance": "5km",//设置距离范围5km
      "location": {    //设置中心经纬度
        "lat":39.915143,
        "lon":116.4039
      }
    }
  }
}
  • 查询对应的范围内的点
GET /hotol/_search
{
  "query": {
    "geo_polygon": {
      "location":{
        "points":[
           {
             "lat":39.915143,
             "lon":116.4039
           },{
             "lat":39.925143,
             "lon":116.4139
           },{
             "lat":39.935143,
             "lon":116.4239
           }
        ]
      }
    }
  }
}

2.9 搜索建议

即在用户输入搜索关键词的过程中系统进行自动补全,用户可以根据自己的需求单击搜索建议的内容直接进行搜索。在搜索时,用户每输入一个字符,前端就需要向后端发送一次查询请求对匹配项进行查询,因此这种场景对后端响应速度的要求比较高。通过协助用户进行搜索,可以避免用户输入错误的关键词,引导用户使用更合适的关键词,提升用户的搜索体验和搜索效率。

  1. 添加字段对应的字段类型需要定义为completion类型
PUT /hotol/_mapping
{
  "properties":{
    "query_word":{ //自定义query_word字段
      "type":"completion"
    }
  }
}
  1. 插入测试数据
POST /hotol/_doc/002
{
  "title":"如家酒店",
  "city":"长春",
  "price":280.5,
  "query_word":"如家快捷酒店"
}
  1. 查询前缀“如家”
GET /hotol/_search
{
  "suggest": {
    "hotel_sug": { //自定义搜索建议名称hotel_sug
      "prefix": "如家",//搜索建议名称
      "completion": {//搜索建议对应字段
        "field": "query_word"
      }
    }
  }
}

注意,ES提供的Completion Suggester功能使用的索引结构不是倒排索引,而是在内存中构建FST(Finite StateTransducers)。构建该数据结构是有比较大的内存存储成本的,因此在生产环境中向索引中添加数据时一定要关注ES节点的内存消耗,避免数据量过大造成ES节点内存耗尽从而影响集群服务。

3 按字段值排序

在默认情况下,ES对搜索结果是按照相关性降序排序的。有时需要按照某些字段的值进行升序或者降序排序 ES提供了sort子句可以对数据进行排序。使用sort子句一般是按照字段信息进行排序,不受相关性影响,而且打分步骤需要耗费一定的硬件资源和时间,因此默认情况下,不对文档进行打分。使用sort排序分为两种类别,一种是按照字段值的大小进行排序,另一种是按照给定地理坐标的距离远近进行排序。

3.1 按普通字段值排序

使用sort子句对字段值进行排序时需要指定排序的字段。ES默认是按照字段值进行升序排序,可以设置order参数为asc或desc,指定按照字段值进行升序或者降序排序。

GET /hotol/_search
{
  "_source": ["title","price"],
  "sort": [
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}

结果中可以看到,使用sort对搜索结果排序后,在每个文档的_source信息下面多出了一个sort信息,该信息中显示了当前文档排序字段的值。

  • 使用sort对搜索结果按照多个字段进行排序

3.2 按地理距离排序

使用geo_distance查询,配合sort可以指定另一种排序规则,即按照文档坐标与指定坐标的距离对结果进行排序。使用时,需要在sort内部指定排序名称为geo_distanc,并指定目的地坐标。除了可以指定升序或者降序排列外,还可以指定排序结果中sort子句中的距离的计量单位,默认值为km即千米。在进行距离计算时,系统默认使用的算法为arc,该算法的特点是计算精准但是耗费时间较长,用户可以使用distance_type参数选择另一种计算速度快但经度略差的算法,名称为plane。文章来源地址https://www.toymoban.com/news/detail-402737.html

GET /hotol/_search
{
  "query": {
    "geo_distance": {
      "distance": "5km",
      "location": { 
        "lat":39.915143,
        "lon":116.4039
      }
    }
  },
  "sort": [
    {
      "_geo_distance": {
          "location": { //设置排序中心点坐标
          "lat":39.915143,
          "lon":116.4039
        },
        "order": "asc",//排序由近及远
        "unit": "km",//排序的计量单位
        "distance_type": "plane"//距离计算方法
      }
    }
  ]
}

到了这里,关于第四章 搜索功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【考研数学】线性代数第四章 —— 线性方程组(1,基本概念 | 基本定理 | 解的结构)

    继向量的学习后,一鼓作气,把线性方程组也解决了去。O.O 方程组 称为 n n n 元齐次线性方程组。 方程组 称为 n n n 元非齐次线性方程组。 方程组(I)又称为方程组(II)对应的齐次线性方程组或导出方程组。 方程组(I)和方程组(II)分别称为齐次线性方程组和非齐次线

    2024年02月11日
    浏览(42)
  • Qt5开发及实例V2.0-第四章Qt基本对话框

    首先介绍标准文件对话框(QFileDialog)、标准颜色对话框(QColorDialog)、标准字体对话框(QFontDialog)、标准输入对话框(QInputDialog)及标准消息对话框(QMessageBox),运行效果如图4.1所示。 按如图4.1所示依次执行如下操作。 (1)单击“文件标准对话框实例”按钮,弹出“文

    2024年02月07日
    浏览(103)
  • 【云计算与虚拟化】第四章 实验二 vCenter Server网络部署及基本操作

    实验二    vCenter Server网络部署及基本操作 一、实验内容 通过vSphere client 客户端登陆vCenter服务器,为新建的虚拟机Windows7 激活,并修改计算机名为姓名拼音的首字母-学号 通过vSphere client 客户端登陆vCenter服务器,将虚拟机windows7的cpu和内存设置为可以热插拔 通过vSphere clie

    2024年04月22日
    浏览(33)
  • 第四章 应用SysML基本特性集的汽车示例 P1|系统建模语言SysML实用指南学习

    仅供个人学习记录 主要就是应用练习建模了 Automobile Domain包 将模型组织入包的包图 汽车规范中包含系统需求的需求图 汽车域块定义图 描述车辆主要功能的用例图

    2024年02月06日
    浏览(46)
  • 【期末不挂科-单片机考前速过系列P4】(第四章:32题搞定基本指令例题)经典例题盘点(带图解析)

    前言 大家好吖,欢迎来到 YY 滴单片机系列 ,热烈欢迎! 本章主要内容面向接触过单片机的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《

    2024年02月02日
    浏览(53)
  • 《Linux操作系统编程》第四章 屏幕编程器vi : 了解屏幕编辑器vi的概述和基本操作命令

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月11日
    浏览(64)
  • 【期末不挂科-考前速过系列P4】单片机[接口与总线]——经典例题盘点(带图解析)(第四章:32题搞定基本指令例题))

    前言 大家好吖,欢迎来到 YY 滴单片机系列 ,热烈欢迎! 本章主要内容面向接触过单片机的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《

    2024年02月02日
    浏览(78)
  • 第四章 Text

    在本章中,您将学习如何在页面上绘制文本。 绘图文本是 PDF 图形中最复杂的部分,但它也是帮助 PDF 击败竞争对手成为当今国际标准的原因。 当其他原始播放器将文本转换为光栅图像或矢量路径(以保持视觉完整性)时,PDF 的发明者知道用户需要可以搜索和复制的文本,而

    2024年02月06日
    浏览(46)
  • 第四章 RPC 调用

    通过以上案例我们发现,Http请求调用服务实例属实过于麻烦。其实对于请求同一个服务,很多步骤都是相同的,例如:服务名,地址,httpClient 创建步骤等。 RPC的出现,就是为了解决这一问题。 RPC: 即我们常说的远程过程调用,就是像调用本地方法一样调用远程方法,通信协

    2024年02月04日
    浏览(49)
  • 四,Eureka 第四章

           2.3.4修改主启动类 标注为Eureka客户端           springcloud-eureka-sever-7001 springcloud-eureka-sever-7001   springcloud-eureka-sever003           5.25编写PaymentMapper接口   5.    

    2024年02月15日
    浏览(82)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包