ElasticSearch查询之——Search API

前言

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

一、ElasticSearch 检索概述

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

GET /_search                        在根目录下检索所有index
GET //_search                在指定索引下检索所有文档
GET /,/_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
Qrery URI测试
(二)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 全文匹配
全文匹配API详解
GET /search_index/_search
{
  "query": {
    "match": {
      "name": {
        "query": "java coder",
        "minimum_should_match": 2
      }
    }
  }
}

minimum_should_match测试用例
GET /search_index/_search
{
  "query": {
    "match": {
      "name": {
        "query": "java coder",
        "operator": "and"
      }
    }
  }
}
operator测试用例
2. Match Phrase Query 字段匹配

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


Match Phrase Query的API示例

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
      }
    }
  }
}
Math Phrase Query测试用例
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)"
      
    }
  }
}
Query String Query测试用例
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"]
    }
  }
}
Simple Query String Query的测试用例
5. Term Query 全词匹配

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

GET /search_index/_search
{
  "query": {
    "term": {
      "name": {
        "value": "java coder"
      }
    }
  }
}
term检索的测试用例
6. Terms Query 多全词匹配

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

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

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

范围匹配API介绍

GET /search_range_index/_search
{
  "query": {
    "range": {
      "birth": {
        "gte": "1995-01-01"
      }
    }
  }
}
Range Query的测试用例1

image.png

Range Query的测试用例2

拓展:


日期计算扩展
(三)复合查询

我们可以发现,之前列举的字段类查询只能够满足单个字段查询条件的使用,当涉及到多个字段时,字段类查询的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 Filter的测试用例
  • Bool Query Must和Must_no
GET /search_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "xiaoming"
          }
        },
        {
          "match": {
            "hobby": "coding"
          }
        }
      ]
    }
  }
}
Bool Query Must的API介绍
  • Bool Query Should
    Should使用分两种情况:
    bool查询中只包含should,不包含must查询以及同时包含should和must查询。我们知道只要文档中数据满足任意一个should条件,那么就可以作为结果呈现出来,相关性算分作为呈现结果顺序的重要依据,满足查询的条件越多,相关性算分会越高
    Bool Query Should的测试用例
(四)Count API

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

GET /search_index/_search
{
  "query": {
    "terms": {
      "name": [
        "java coder",
        "xiaoming"
      ]
    }
  }
}
Count API的测试用例
(五)Source Filter

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


source filter的API讲解
GET /search_index/_search
{
  "query": {
    "terms": {
      "name": [
        "java coder",
        "xiaoming"
      ]
    }
  },
  "_source": ["name","job"]
}
source filter的测试用例

你可能感兴趣的:(ElasticSearch查询之——Search API)