ES基础篇 常用API之搜索API(URL搜索)

文章目录

  • 前言
  • 搜索结构
  • 参数详解
    • 输出格式
    • 输出字段
    • 字段排序
    • 分页处理
    • 搜索范围
      • 指定字段
      • 泛搜索
    • 搜索语法
      • 双引号搜索
      • 不带双引号搜索
      • 括号搜索
      • 范围查询
      • 算术符号
      • 通配符查询

前言

之前分别介绍了ES的一下常用API:索引类、映射类、别名类API和文档类API, 这些API对应关系型数据也就是创建库、表、添加数据等操作,可以让我们开始基本操作, 但数据库本身的意义无非就是存储和搜索,并且搜索的比例会远远大于存储的比例(大约8:2),所以很有必要了解学习搜索类的API
搜索是ElasticSearch的核心功能,ElasticSearch为用户提供了多种搜索方式,大致分为两类:URL SearchRequest Body Search

  • URL Search
    在URL中使用查询参数
  • Request Body Search
    使用 Elasticsearch 提供的,基于 JSON 格式的格式更加完备的 Query Dpmain Specific Language (DSL)
    本章节主要介绍URL Search,此搜索方式在生产中或许使用较少,但开发过程中会经常使用,我们在开发过程中会经常遇到校验数据、查看结果等操作,URL Search明显比DSL更加便捷,所以了解学习URL Search还是很有必要的

搜索结构

查询时,通过将参数追加在请求地址url后,类似编程中Get请求方式携带参数。

这种方式简单便捷,适用于临时在命令行使用一些工具,比如curl,快速发出请求,来检索想要的信息;但如果查询请求很复杂,是很难构建的。故主要用于开发中,生产环境几乎很少使用

GET localhost:8888/blog/_search?q=content:keyword&df=title&sort=createtime:desc&from=0&size=10&timeout=1s
{
  "profile": "true"
}

参数说明:

  • q参数指定查询语句,适用Query String Syntax
  • df默认字段,q参数不指定字段时,df用于设置默认字段
  • sort排序
  • fromsize 用于分页
  • Profile 可以查看查询时如何被执行的
参数 说明
q 查询字符串(映射到query_string查询,有关详细信息,请参阅 查询字符串查询)。
df 在查询中未定义字段前缀时使用的默认字段。
analyzer 分析查询字符串时要使用的分析器名称。
analyze_wildcard 是否应分析通配符和前缀查询。默认为false
batched_reduce_size 应在协调节点上一次减少的分片结果数。如果请求中潜在的分片数量很大,则应将此值用作保护机制,以减少每个搜索请求的内存开销。
default_operator 要使用的默认运算符可以是ANDOR。默认为OR
lenient 如果设置为true将导致忽略基于格式的失败(如向数字字段提供文本)。默认为false。
explain 对于每个命中,包含如何计算命中得分的解释。
_source 设置为false禁用_source字段检索。您还可以使用_source_include&检索部分文档_source_exclude( 有关详细信息,请参阅请求正文文档)
stored_fields 每个匹配返回的文档的选择性存储字段,逗号分隔。不指定任何值将导致没有字段返回。
sort 排序执行。可以是fieldNamefieldName:asc/ 的形式fieldName:desc。fieldName可以是文档中的实际字段,也可以是特殊_score名称,表示基于分数的排序。可以有几个sort参数(顺序很重要)。
track_scores 排序时,设置为true仍然跟踪分数并将其作为每个匹配的一部分返回。
track_total_hits 设置为false禁用跟踪与查询匹配的匹配总数。(有关详细信息,请参阅索引排序)。默认为true。
timeout 搜索超时,将搜索请求限制在指定的时间值内执行,并使用在到期时累积的点击数进行保释。默认为无超时。
terminate_after 在达到查询执行将提前终止时,为每个分片收集的最大文档数。如果设置,响应将具有一个布尔字段,terminated_early以指示查询执行是否实际上已终止。默认为no terminate_after。
from 从命中的索引开始返回。默认为0
size 要返回的点击次数。默认为10
search_type 要执行的搜索操作的类型。可以是 dfs_query_then_fetchquery_then_fetch。默认为query_then_fetch。有关可以执行的不同搜索类型的更多详细信息,请参阅 搜索类型
allow_partial_search_results false如果请求将产生部分结果,则设置为返回整体故障。默认为true,这将允许在超时或部分失败的情况下获得部分结果。

参数详解

输出格式

format, 该字段用于指定查询结果的返回格式,支持json、text、yaml等,默认为json

GET /${index}/_search?format=${format_type}

例如:

搜索指定索引的文档,以yaml格式输出

  • 输入

    GET /nav_web_video/_search?format=yaml
    
  • 输出

    took: 0
    timed_out: false
    _shards:
      total: 1
      successful: 1
      skipped: 0
      failed: 0
    hits:
      total:
        value: 5
        relation: "eq"
      max_score: 1.0
      hits:
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sFXLs4gBtZh8w2gvDlGk"
        _score: 1.0
        _source:
          name: "爱奇艺"
          url: "https://www.iqiyi.com/"
          company: "北京爱奇艺科技有限公司"
          userNum: "120000000"
          foundName: "龚宇"
          foundTime: "2010-02-24"
          ipAddr: "110.242.72.5"
          desc: "爱奇艺(iQIYI.COM)是拥有海量、优质、高清的网络视频的大型视频网站,专业的网络视频播放平台。爱奇艺影视内容丰富多元,涵盖电影、电视\
            剧、动漫、综艺、生活、音乐、搞笑、财经、军事、体育、片花..."
          createTime: "2021-03-23"
      ……    
    

在搜索过程中,我们可以通过指定URL中的参数q或者df指定我们需要搜索的字段,如果不指定,将会在所有字段中进行搜索

输出字段

_source, 该字段用于指定返回数据的指定字段,多个字段以,分隔,设置为false时,禁用_source字段检索

_source_include, 该字段用于指定返回包含的字段

_source_exclude, 该字段用于指定排除不需要显示的字段

GET /${index}/_search?&format=yaml&_source=${filed1},${filed2},${filed3}

例如:

以指定的字段返回文档数据

  • 输入

    GET /nav_web_video/_search?&format=yaml&_source=name,company,foundName
    
  • 输出

    took: 1
    timed_out: false
    _shards:
      total: 1
      successful: 1
      skipped: 0
      failed: 0
    hits:
      total:
        value: 5
        relation: "eq"
      max_score: 1.0
      hits:
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sFXLs4gBtZh8w2gvDlGk"
        _score: 1.0
        _source:
          foundName: "龚宇"
          name: "爱奇艺"
          company: "北京爱奇艺科技有限公司"
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sVXLs4gBtZh8w2gvDlGk"
        _score: 1.0
        _source:
          foundName: "马化腾"
          name: "腾讯视频"
          company: "腾讯科技有限公司"
      ……
    

字段排序

sort,该字段用于对查询的文档进行排序,可接受多个字段排序

GET /${index}/_search?&sort=${field1}:desc,${field2}:asc

例如:

将查询的文档进行排序

  • 输入

    GET /nav_web_video/_search?&format=yaml&_source=name,foundTime,userNum&sort=userNum:desc,foundTime:desc 
    
  • 输出

    took: 1
    timed_out: false
    _shards:
      total: 1
      successful: 1
      skipped: 0
      failed: 0
    hits:
      total:
        value: 5
        relation: "eq"
      max_score: null
      hits:
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sVXLs4gBtZh8w2gvDlGk"
        _score: null
        _source:
          userNum: "120000000"
          foundTime: "2011-04-01"
          name: "腾讯视频"
        sort:
        - 120000000
        - 1301616000000
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sFXLs4gBtZh8w2gvDlGk"
        _score: null
        _source:
          userNum: "120000000"
          foundTime: "2010-02-24"
          name: "爱奇艺"
        sort:
        - 120000000
        - 1266969600000
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "s1XLs4gBtZh8w2gvDlGk"
        _score: null
        _source:
          userNum: "102000000"
          foundTime: "2006-06-21"
          name: "优酷视频"
        sort:
        - 102000000
        - 1150848000000
    ……
    

分页处理

from, 该字段用于指定页码, 从0开始,相当于pageNo

size, 该字段用于指定每页多少条数据,相当于pageSize

如果没有发送这两个参数, Elasticsearch 默认从第一项结果开始(第0 项结果),在回复 中返回 10 项结果

需要注意的是,为了确定第2 页的10 项结果, Elastic search 必须要计算前20 个结果,如果结果集合不断增加,获取某些靠

后的翻页将会成为代价高昂的操作

GET /${index}/_search?&from=${pageNo}&size=${pageSize}

例如:

查询索引下的文档,从第0页开始,每页显示2条文档

  • 输入

    GET /nav_web_*/_search?&format=yaml&_source=name&from=0&size=2
    
  • 输出

    ---
    took: 1
    timed_out: false
    _shards:
      total: 3
      successful: 3
      skipped: 0
      failed: 0
    hits:
      total:
        value: 15
        relation: "eq"
      max_score: 1.0
      hits:
      - _index: "nav_web_game"
        _type: "_doc"
        _id: "m1Xpi4gBtZh8w2gvcFFt"
        _score: 1.0
        _source:
          name: "腾讯游戏"
      - _index: "nav_web_game"
        _type: "_doc"
        _id: "nFXpi4gBtZh8w2gvcFFt"
        _score: 1.0
        _source:
          name: "百度游戏"
    
    

搜索范围

  • q, 该参数用于指定搜索的关键词,不使用该参数时代表搜索所有文档,可指定搜索字段,如:q= f i e l d : {field}: field:{keyword}

  • df, 如若q参数未指定搜索字段,将使用此参数携带的字段

qdf参数均为指定搜索字段,将会使用泛搜索

指定字段

# field为指定的具体字段,keyword为搜索的关键字
GET /${index}/_search?q=${field}:${keyword}

例如:

在创建的索引中使用指定字段搜索

  • 输入

    GET /nav_web_video/_search?format=yaml&q=name:腾讯平台
    
  • 输出

    took: 1
    timed_out: false
    _shards:
      total: 1
      successful: 1
      skipped: 0
      failed: 0
    hits:
      total:
        value: 1
        relation: "eq"
      max_score: 1.1213677
      hits:
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sVXLs4gBtZh8w2gvDlGk"
        _score: 1.1213677
        _source:
          name: "腾讯视频"
          url: "https://v.qq.com/"
          company: "腾讯科技有限公司"
          userNum: "120000000"
          foundName: "马化腾"
          foundTime: "2011-04-01"
          ipAddr: "113.56.189.242"
          desc: "腾讯视频致力于打造中国领先的在线视频媒体平台,以丰富的内容、极致的观看体验、便捷的登录方式、24小时多平台无缝应用体验以及快捷分享的产品特\
            性,主要满足用户在线观看视频的需求..."
          createTime: "2021-06-23"
    

泛搜索

es中的_all元数据,在建立索引的时候,我们插入一条document,它里面包含了多个field,此时,es会自动将多个field的值,全部用字符串的方式串联起来,变成一个长的字符串,作为_all field的值,同时建立索引

如果在搜索的时候,没有对某个field指定搜索,就默认搜索_all field,其中是包含了所有field的值的

# keyword为搜索的关键字
GET /${index}/_search?q=${keyword}

样例:

在创建的索引中,在所有的字段中搜索

  • 输入

    GET /nav_web_video/_search?format=yaml&_source=name,desc&q=腾讯平台
    
  • 输出

    ---
    took: 3
    timed_out: false
    _shards:
      total: 1
      successful: 1
      skipped: 0
      failed: 0
    hits:
      total:
        value: 2
        relation: "eq"
      max_score: 1.9663699
      hits:
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sVXLs4gBtZh8w2gvDlGk"
        _score: 1.9663699
        _source:
          name: "腾讯视频"
          desc: "腾讯视频致力于打造中国领先的在线视频媒体平台,以丰富的内容、极致的观看体验、便捷的登录方式、24小时多平台无缝应用体验以及快捷分享的产品特\
            性,主要满足用户在线观看视频的需求..."
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sFXLs4gBtZh8w2gvDlGk"
        _score: 0.70999944
        _source:
          name: "爱奇艺"
          desc: "爱奇艺(iQIYI.COM)是拥有海量、优质、高清的网络视频的大型视频网站,专业的网络视频播放平台。爱奇艺影视内容丰富多元,涵盖电影、电视\
            剧、动漫、综艺、生活、音乐、搞笑、财经、军事、体育、片花..."
    

搜索语法

双引号搜索

双引号搜索, 即Phrase短语搜索,使用双引号括起查询字符串时,它将被视为一个精确短语匹配。只有包含完全相同短语的文档才会被返回

  • 双引号内的作为短语精确匹配,不会分词
  • 双引号的会进行分词,并且会在所有字段中进行检索匹配
# 括号内的keyword1和keyword2不会进行分词,并且顺序必须一致, 括号外keyword3会进行分词并且泛查询
GET /${index}/_search?q=${field}:"${keyword1} ${keyword2}"${keyword3}
{
  "profile": "true"
}

例如

指定索引中搜索"腾讯TV"电影关键词的文档

  • 输入

    # 双引号中的"腾讯TV"在所有文档的name字段中无法找到,所以匹配不到;而"都市电影"通过分词后可以在爱奇艺和优酷视频的desc中找到,所以可以匹配
    GET /nav_web_video/_search?format=yaml&_source=name&q=name:"腾讯TV"都市电影
    
  • 输出

    ---
    took: 3
    timed_out: false
    _shards:
      total: 1
      successful: 1
      skipped: 0
      failed: 0
    hits:
      total:
        value: 2
        relation: "eq"
      max_score: 1.5778974
      hits:
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sFXLs4gBtZh8w2gvDlGk"
        _score: 1.5778974
        _source:
          name: "爱奇艺"
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "s1XLs4gBtZh8w2gvDlGk"
        _score: 1.453199
        _source:
          name: "优酷视频"
    

不带双引号搜索

不使用双引号括起查询字符串,则 Elasticsearch 将使用默认分词器对查询字符串进行分析,并根据特定的分析规则处理搜索词汇

  • q指定字段

    q指定字段时,ES会将距离q最近的关键词根据设置的分词器进行分词,并在指定的字段中检索相关文档,只要相关字段中包含被分词的内容即可被检索到;空格后面的词依然会被分词器进行分词,但会在所有字段中进行泛搜索

  • q不指定字段时,所有关键词都会进行分词,并在所有字段中进行检索,只要有匹配的即可被检索到

例如:

在指定索引中检索不带双引号的腾讯TV 都市电影

  • 输入

    # 短语将会被分词分为“腾讯”、“TV”、“都市”、“电影”,"腾讯"和“TV”关键词将会被在name字段中搜索, 其他字段将会在所有字段进行泛搜索
    GET /nav_web_video/_search?format=yaml&_source=name&q=name:腾讯TV 都市电影
    
  • 输出

    ---
    took: 2
    timed_out: false
    _shards:
      total: 1
      successful: 1
      skipped: 0
      failed: 0
    hits:
      total:
        value: 4
        relation: "eq"
      max_score: 1.6777123
      hits:
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "slXLs4gBtZh8w2gvDlGk"
        _score: 1.6777123
        _source:
          name: "芒果TV"
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sFXLs4gBtZh8w2gvDlGk"
        _score: 1.5778974
        _source:
          name: "爱奇艺"
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "s1XLs4gBtZh8w2gvDlGk"
        _score: 1.453199
        _source:
          name: "优酷视频"
      - _index: "nav_web_video"
        _type: "_doc"
        _id: "sVXLs4gBtZh8w2gvDlGk"
        _score: 1.1213677
        _source:
          name: "腾讯视频"
    

括号搜索

在ES中,URL查询语法使用的是Lucene查询语法,可以使用括号来分组和控制查询优先级。具体来说,括号可用于将多个条件组合成一个逻辑表达式,并控制它们之间的优先级。

  • 布尔操作

    • AND / OR / NOT 或者 && / || / !

    • 必须大写

    • title:(matrix NOT reloaded)

    # type:BooleanQuery,field中必须包含 keyword1 和 keyword2
    GET /${index}/_search?q=${field}:(${keyword1} AND ${keyword2})
    
    #type:BooleanQuery, field中必须包含 keyword1,但不包括 keyword2
    GET /${index}/_search?q=${field}:(${keyword1} NOT ${keyword2})
    
    
    #type:BooleanQuery, field中包含 keyword1,或者包括 keyword2, OR可以省略
    GET /${index}/_search?q=${field}:(${keyword1} OR ${keyword2})
    

    样例:

    • 输入

      # 必须包含咪咕视频和腾讯视频
      GET /nav_web_video/_search?format=yaml&_source=name&q=name:(咪咕TV AND 腾讯电影)
      # 包含咪咕视频或者腾讯视频
      GET /nav_web_video/_search?format=yaml&_source=name&q=name:(咪咕TV  腾讯电影)
      # 必须包含咪咕视频,但不包含腾讯视频
      GET /nav_web_video/_search?format=yaml&_source=name&q=name:(咪咕TV NOT 腾讯电影)
      
    • 输出

       # 1 必须包含咪咕视频和腾讯视频
      ---
      took: 7
      timed_out: false
      _shards:
        total: 1
        successful: 1
        skipped: 0
      failed: 0
      hits:
       total:
         value: 0
        relation: "eq"
       max_score: null
       hits: []
      
      # 2 包含咪咕视频或者腾讯视频
      ---
      took: 23
      timed_out: false
      _shards:
      	total: 1
      	successful: 1
      	skipped: 0
      	failed: 0
      hits:
      	total:
      		value: 3
      		relation: "eq"
      	max_score: 2.8478818
      	hits:
      	- _index: "nav_web_video"
      	  _type: "_doc"
      	  _id: "tFXLs4gBtZh8w2gvDlGk"
      	  _score: 2.8478818
            _source:
        		name: "咪咕视频"
      	- _index: "nav_web_video"
      	  _type: "_doc"
            _id: "slXLs4gBtZh8w2gvDlGk"
            _score: 1.6777123
            _source:
         		name: "芒果TV"
      	- _index: "nav_web_video"
      	  _type: "_doc"
      	  _id: "sVXLs4gBtZh8w2gvDlGk"
            _score: 1.1213677
            _source:
        		name: "腾讯视频"
      
      # 3 必须包含咪咕视频,但不包含腾讯视频
      ---
      took: 3
      timed_out: false
      _shards:
      	total: 1
      	successful: 1
      	skipped: 0
      	failed: 0
      hits:
      	total:
      		value: 2
      		relation: "eq"
      	max_score: 2.8478818
      	hits:
      	- _index: "nav_web_video"
      		_type: "_doc"
      		_id: "tFXLs4gBtZh8w2gvDlGk"
      		_score: 2.8478818
      		_source:
        			name: "咪咕视频"
      	- _index: "nav_web_video"
      		_type: "_doc"
      		_id: "slXLs4gBtZh8w2gvDlGk"
      		_score: 1.6777123
      		_source:
        			name: "芒果TV"
      
  • 加减操作

    • + 表示must
    • -表示nust_not
    • 样式:title:(+matrix -reloaded)
    # BooleanQuery,field 中必须包含 keyword2,不包含 keyword1
    GET /${index}/_search?q=${filed}:(-${keyword1} + ${keyword2})
    {
      "profile": "true"
    }
    

    样例:

    • 输入

        # BooleanQuery, name中必须包含"腾讯视频", 不包含"咪咕视频"
        GET /nav_web_video/_search?format=yaml&_source=name&q=name:(-咪咕TV +腾讯电影)
      
    • 输出

      ---
      took: 1
      timed_out: false
      _shards:
      	total: 1
      	successful: 1
      	skipped: 0
      failed: 0
      hits:
      	total:
        		value: 1
      		relation: "eq"
      	max_score: 1.1213677
      	hits:
      	- _index: "nav_web_video"
        		_type: "_doc"
      		_id: "sVXLs4gBtZh8w2gvDlGk"
        		_score: 1.1213677
      		_source:
          		name: "腾讯视频"
      

范围查询

year:{2019 TO 2018}
year:[* TO 2018]

  • []表示闭区间,指包含端点的区间

  • {}表示开区间,指不包含端点的区间

样例:

搜索时间范围在2010-02-24(不包含)至2011-04-01(包含)之间的数据

  • 输入
    #花括号2010-02-24不包含,中括号2011-04-01包含
    GET /nav_web_video/_search?format=yaml&_source=name,foundTime&q=foundTime:{2010-02-24 TO 2011-04-01]
    
  • 输出
    ---
    took: 4
    timed_out: false
    _shards:
    	total: 1
    	successful: 1
    	skipped: 0
    	failed: 0
    hits:
    	total:
    		value: 1
    		relation: "eq"
    	max_score: 1.0
    	hits:
    	- _index: "nav_web_video"
    	  _type: "_doc"
    	  _id: "sVXLs4gBtZh8w2gvDlGk"
    	  _score: 1.0
    	  _source:
      		foundTime: "2011-04-01"
      		name: "腾讯视频"
    

算术符号

在ES的URL搜索中,可以使用算术符号来进行范围查询或数学运算, 可以使用TO<>=AND等常用符号来进行范围查询, 除此ES还支持基本的算术符号(+、-、*、/)和一些高级数学运算符,例如:^(指数运算)、%(取模运算)、abs、floor、ceil等。

year:>2010
year:(>2010 AND <=2018)
year:(+>2010 AND +<=2018)

  • 在计算时间范围时, ES会将时间转换为毫秒时间戳与存储字段进行对比, 即使存储为年月日时分秒, 查询时既可以只使用年或年月进行查询, 因为ES会将传入值转换为时间戳进行对比
  • 在查询一段范围时, 可以使用小括号, 中间使用AND链接

例如:

#查询foundTime大于2011年的文档
GET /nav_web_video/_search?format=yaml&_source=name,foundTime&q=foundTime:>2011
#查询foundTime大于2011年 小于2015的文档
GET /nav_web_video/_search?format=yaml&_source=name,foundTime&q=foundTime:(>2011 AND <2015)
#查询foundTime大于等于2011年 小于2015的文档
GET /nav_web_video/_search?format=yaml&_source=name,foundTime&q=foundTime:(+>=2011 AND +<2015)

通配符查询

在 Elasticsearch 中,通配符搜索时,URL 字段中多个汉字通配符(* 或 ?)默认是无法匹配的。这是因为中文的分词和字典匹配会影响通配符查询的效果,导致查询结果不准确或者查询失败。此外,通配符查询还会增加查询的时间和复杂度,影响 Elasticsearch 的性能。因此,在 Elasticsearch 中不建议使用多个汉字通配符进行通配符搜索。

通配符查询效率低,占用内容大,不建议使用。特别是放在最前面

  • ?代表 1 个字符,* 代表 0 或多个字符

    • title:mi?d
    • title:be*
      #通配符匹配
      GET /blog/_search?q=?par*
      {
        "profile": "true"
      }
    
  • 正则表达

    • title:[bt]oy
  • 模糊匹配与近似查询

    • title:befutifl~1
    • title:”lord rings” ~2
      #模糊匹配
      GET /blog/_search?q=elastccssarch~5
      {
       "profile": "true"
      }
    
      #近似查询
      GET /blog/_search?q="to docker"~5
      {
        "profile": "true"
      }
    

你可能感兴趣的:(ES从入门到跑路,elasticsearch,大数据,java)