ElasticSearch查询之——Search API

前言

对于索引映射的定义一般只需要定义一次,在日常工作中,我们更多的时候是在ElasticSearch(简称ES)中查询数据,那么我们可以如何在ES中处理多条件查询语句呢?ES中一共提供了哪些查询的形式给我们实现搜索呢?同时,检索出来的数据,又是通过什么方式来进行排序的呢?本文将围绕ElasticSearch查询相关的API,对上述问题进行一一讲解。希望能够给各位读者参考。

一、ElasticSearch 检索概述

实现对ES中存储的数据进行查询分析,使用的关键字是_search,比如下面的API

GET /_search                        在根目录下检索所有index
GET /<target>/_search                在指定索引下检索所有文档
GET /<target1>,<target2>/_search     检索指定多个索引下的所有文档 
GET /my_*/_search                  和上面一条一样,区别在于这一条命令使用了通配符
  • 查询的两种形式
    ES给使用者提供了URI SearchRequest Body Search 两种方式来进行查询,下面将对两种查询方式的特点进行简单介绍:
    URI Search:操作简便,方便通过命令行测试-仅包含部分查询语法
    Request Body Search:ES为这种查询方式提供了完备查询语法Query DSL(Domain Specific Language)

二、URI Search

(一)常用参数
参数 含义
q 指定查询的语句,语法为Query String Syntax
df q中不指定字段时默认查询的字段,如果不指定,es 会查询所有字段
sort 排序
timeout 指定超时时间,默认不超时
from,size 用于分页

小例子:查询job字段中包含java的文档,结果根据age属性进行升序排序,返回第1个文档,如果超过1s没有结束,则以超时结束。

PUT /search_index/_doc/1
{
  "name" : "java coder",
  "hobby" : "coding",
  "job" : "java enginger",
  "age" : 4
}
PUT /search_index/_doc/2
{
  "name" : "xiaoming",
  "hobby" : "coding",
  "job" : "java enginger",
  "age" : 16
}
PUT /search_index/_doc/3
{
  "name" : "xiaoming",
  "hobby" : "coding",
  "job" : "java enginger",
  "age" : 16
}
PUT /search_index/_doc/4
{
  "name" : "xiaoming",
  "hobby" : "talking",
  "job" : "teacher",
  "age" : 20
}
PUT /search_index/_doc/5
{
  "name" : "xiaoming",
  "hobby" : "work",
  "job" : "worker",
  "age" : 11
}

GET /search_index/_search?q=java&df=job&sort=age:desc&from=0&size=1&timeout=1s
(二)Query URI查询详讲
1. term与phrase (词匹配和词语匹配)
# 检索数据和上面的保持一致
GET /search_index/_search?q=java xiaoming

多词匹配之间使用空格进行隔开,词语之间的关系为“或”

若想使用词语匹配,需要用双引号括起来

# 检索数据和上面的保持一致
GET /search_index/_search?q="java coder"
2. 泛查询和指定字段查询

泛查询在之前其实就有演示过,即像q = xiaoming这种不指定检索字段范围,会在所有字段中进行检索的查询即称为泛查询。反之,如果指定了字段,就能大大缩小范围。常见的指定字段的方式为字段:检索条件字符

GET /search_index/_search?q=name:java coder
3. 布尔操作符

SearchURI中也可以使用和和Query DSL类型的布尔操作符,不过具体的使用规则略有不同,具体的规则如下:

Search URI参数 Query DSL中的等价参数
AND 等价于&&,也就是且
OR 等价于||,也就是或
NOT 等价于!,也就是非
- 等价于must_no,和OR的功能差不多
+ 等价于must
# 新加一个测试数据,便于区别测试
PUT /search_index/_doc/6
{
  "name" : "xiaohong",
  "hobby" : "coding",
  "job" : "enginger",
  "age" : 16
}


GET /search_index/_search?q=job:(java AND enginger)

GET /search_index/_search?q=job:(java OR enginger)

GET /search_index/_search?q=job:(NOT java  enginger)

GET /search_index/_search?q=job:((NOT java  enginger) || (worker -teacher))

需要注意的是,“+”号在url中会被解析为空格,要使用encode后的结果才可以,我们需要用%2B来替代一下。

4. 范围查询

范围查询支持数据范围和日期范围的查询,具体的表达式写法有两种方式:

区间写法,闭区间用[ ],开区间用{ } (开区间这种写法可能有些版本的ES不支持了)
  • 数值写法,类似于我们sql的正常写法
  • GET /search_index/_search?q=age:(>=16 AND <=20)
    
    5. 通配符查询
    GET /search_index/_search?q=name:ja??
    
    GET /search_index/_search?q=name:ja*
    

    Query URI支持我们使用通配符来进行模糊查询,?表示一个字符,*表示一个或者多个字符

    注意:通配符匹配执行效率低,且占用较多内存,数据较多时不建议使用
    如无特殊需求,不要将?/*放在最前面(因为会加大匹配的范围,降低匹配效率)

    6. 正则表达式匹配

    Query URI支持我们使用正则表达式来进行检索

    GET /search_index/_search?q=name:/jav[abcd]/
    
    7. 近似值匹配和模糊匹配

    当我们对于检索条件字符不明确时,Query URI支持我们使用近似值来作为模糊查询的条件,这个和之前的通配符不太一样,通配符很多时候是基于我们清楚某一段字符中的某个区间内容了(比如说最终的结果是xiaoming,我们可以根据知道的字符进行匹配,比如xiao**ming)。而近似值匹配可以是众多模糊匹配的并集。

    • 近似值匹配 fuzzy query
    GET /search_index/_search?q=name:jave~1
    
    • 模糊值匹配 proximity search
      相比于近似值匹配来说,模糊值匹配的计量单位从字符变成了单词
    PUT /search_index/_doc/7
    {
      "name" : "java coder master",
      "hobby" : "coding",
      "job" : "java enginger",
      "age" : 4
    }
    
    GET /search_index/_search?q="java master"~1
    

    三、Request Body Search

    Request Body Search字如其意,就是通过在body中添加请求体来实现搜索。我们在第二节中学习了Query URI的众多语法可能会觉得它已经很强大,但实际上第三节的将要介绍的Query DSL会更加强大和灵活,不仅支持URI写法的所有语法,还支持更多高阶的语法查询。也是我们日常工作中更为常用的一种检索方式。

    (一)Query DSL的简单使用
    (二)字段类查询

    字段类的查询可以分为全文匹配和单词匹配,两者的区别在于会不会对查询语句进行分词后处理,全文匹配会(match、match_phrase),单词匹配(term、terms、range)不会。

    1. match 全文匹配
    GET /search_index/_search
    {
      "query": {
        "match": {
          "name": {
            "query": "java coder",
            "minimum_should_match": 2
          }
        }
      }
    }
    
    
    GET /search_index/_search
    {
      "query": {
        "match": {
          "name": {
            "query": "java coder",
            "operator": "and"
          }
        }
      }
    }
    
    2. Match Phrase Query 字段匹配

    该方法用于对字段作检索,对字段有顺序要求


    
    PUT /search_index2/_doc/1
    {
      "name": "sun wukong",
      "age": 100
    }
    PUT /search_index2/_doc/2
    {
      "name": "wukong sun",
      "age": 100
    }
    PUT /search_index2/_doc/3
    {
      "name": "sun wukong test",
      "age": 100
    }
    
    GET /search_index2/_search
    {
      "query": {
        "match_phrase": {
          "name": {
            "query": "sun test",
            "slop": 1
          }
        }
      }
    }
    
    3. Query String Query

    Query String Query其实就相当于Query URI的请求体写法

    GET /search_index/_search
    {
      "query": {
        "query_string": {
          "fields": ["name"],
          "query": "java AND coder OR (master loser)"
          
        }
      }
    }
    
    4. Simple Query String Query 简单匹配

    Simple Query String Query类似于Query String,但是会忽略错误的查询语法,并且仅支持部分查询语法。其常用的逻辑符号如下,不能使用AND、OR、NOT等关键词,而是要对应地使用+ | -

    GET /search_index/_search
    {
      "query": {
        "simple_query_string": {
          "query": "java NOT coder",
          "fields": ["name"]
        }
      }
    }
    
    
    GET /search_index/_search
    {
      "query": {
        "simple_query_string": {
          "query": "java -coder",
          "fields": ["name"]
        }
      }
    }
    
    5. Term Query 全词匹配

    Term Query将查询语句作为整个单词进行查询,即不对查询语句做分词处理

    GET /search_index/_search
    {
      "query": {
        "term": {
          "name": {
            "value": "java coder"
          }
        }
      }
    }
    
    6. Terms Query 多全词匹配

    terms queryterm query类似,差别在于后者可以同时支持多个全词匹配

    GET /search_index/_search
    {
      "query": {
        "terms": {
          "name": [
            "java coder",
            "xiaoming"
          ]
        }
      }
    }
    
    7. Range Query 范围匹配

    Query DSL支持我们使用Range Query来使用范围匹配

    GET /search_range_index/_search
    {
      "query": {
        "range": {
          "birth": {
            "gte": "1995-01-01"
          }
        }
      }
    }
    



    拓展:


    (三)复合查询

    我们可以发现,之前列举的字段类查询只能够满足单个字段查询条件的使用,当涉及到多个字段时,字段类查询的matchterm等API就无能为力了。满足这种多字段检索需要的方式是使用复合查询。
    ·复合查询是指包含字段类查询或复合查询的类型,主要包括以下几类∶constant_score querybool querydis_max queryfunction_score queryboosting query
    这里的话,主要讲一下布尔查询Bool Query

    API 含义
    filter 只过滤符合条件的文档,不计算相关性得分
    must 文档必须符合must中的所有条件,会影响相关性得分
    must_not 文档必须不符合must_not中的所有条件
    should 文档可以符合should 中的条件,会影响相关性得分
    • Bool Query Filter
    GET /search_index/_search
    {
      "query": {
        "bool": {
          "filter": {
            "term": {
              "hobby": "coding"
            }
          }
        }
      }
    }
    
    • Bool Query Must和Must_no
    GET /search_index/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "name": "xiaoming"
              }
            },
            {
              "match": {
                "hobby": "coding"
              }
            }
          ]
        }
      }
    }
    
    Bool Query Should
    Should使用分两种情况:
    bool查询中只包含should,不包含must查询以及同时包含should和must查询。我们知道只要文档中数据满足任意一个should条件,那么就可以作为结果呈现出来,相关性算分作为呈现结果顺序的重要依据,满足查询的条件越多,相关性算分会越高
    (四)Count API

    当我们不需要获取详细的文档信息,只需要获取命中的文档数量时,就可以使用count来获取我们想要的结果。

    GET /search_index/_search
    {
      "query": {
        "terms": {
          "name": [
            "java coder",
            "xiaoming"
          ]
        }
      }
    }
    
    (五)Source Filter

    当我们只需要获取命中文档的指定字段值时,我们可以通过source来指定我们需要es返回的值


    GET /search_index/_search
    {
      "query": {
        "terms": {
          "name": [
            "java coder",
            "xiaoming"
          ]
        }
      },
      "_source": ["name","job"]
    }
    
    posted @   moutory  阅读(130)  评论(0编辑  收藏  举报  
    相关博文:
    阅读排行:
    · 震惊!C++程序真的从main开始吗?99%的程序员都答错了
    · winform 绘制太阳,地球,月球 运作规律
    · 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
    · 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
    · 上周热点回顾(3.3-3.9)
    点击右上角即可分享
    微信分享提示