1. 查询

上一篇文章展示了ElasticSearch的一些基本操作,下面主要介绍ElasticSearch的查询相关操作

查询所有:

1
GET /{index}/_search

根据id查询:

1
GET /{index}/{type}/{id}

除了上述简单查询之外。elasticsearch作为搜索引擎,最复杂最强大的功能就是搜索查询功能。包括:匹配查询、词条查询、模糊查询、组合查询、范围查询、高亮、排序、分页等等查询功能。

基本查询语法如下:

1
2
3
4
5
6
7
8
GET /索引库名/_search
{
"query":{
"查询类型":{
"查询条件":"查询条件值"
}
}
}

这里的query代表一个查询对象,里面可以有不同的查询属性

  • 查询类型:
    • 例如:match_allmatchtermrange 等等
  • 查询条件:查询条件会根据类型的不同,写法也有差异,后面详细讲解

查询结果:

  • took:查询花费时间,单位是毫秒
  • time_out:是否超时
  • _shards:分片信息
  • hits:搜索结果总览对象
    • total:搜索到的总条数
    • max_score:所有结果中文档得分的最高分
    • hits:搜索结果的文档对象数组,每个元素是一条搜索到的文档信息
      • _index:索引库
      • _type:文档类型
      • _id:文档id
      • _score:文档得分
      • _source:文档的源数据

1.1. 数据准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST /mall/goods/_bulk
{"index":{"_id":1}}
{ "title":"小米手机", "images":"http://image.jd.com/12479122.jpg", "price":1999, "stock": 200, "attr": { "category": "手机", "brand": "小米" } }
{"index":{"_id":2}}
{"title":"超米手机", "images":"http://image.jd.com/12479122.jpg", "price":2999, "stock": 300, "attr": { "category": "手机", "brand": "小米" } }
{"index":{"_id":3}}
{ "title":"小米电视", "images":"http://image.jd.com/12479122.jpg", "price":3999, "stock": 400, "attr": { "category": "电视", "brand": "小米" } }
{"index":{"_id":4}}
{ "title":"小米笔记本", "images":"http://image.jd.com/12479122.jpg", "price":4999, "stock": 200, "attr": { "category": "笔记本", "brand": "小米" } }
{"index":{"_id":5}}
{ "title":"华为手机", "images":"http://image.jd.com/12479122.jpg", "price":3999, "stock": 400, "attr": { "category": "手机", "brand": "华为" } }
{"index":{"_id":6}}
{ "title":"华为笔记本", "images":"http://image.jd.com/12479122.jpg", "price":5999, "stock": 200, "attr": { "category": "笔记本", "brand": "华为" } }
{"index":{"_id":7}}
{ "title":"荣耀手机", "images":"http://image.jd.com/12479122.jpg", "price":2999, "stock": 300, "attr": { "category": "手机", "brand": "华为" } }
{"index":{"_id":8}}
{ "title":"oppo手机", "images":"http://image.jd.com/12479122.jpg", "price":2799, "stock": 400, "attr": { "category": "手机", "brand": "oppo" } }
{"index":{"_id":9}}
{ "title":"vivo手机", "images":"http://image.jd.com/12479122.jpg", "price":2699, "stock": 300, "attr": { "category": "手机", "brand": "vivo" } }
{"index":{"_id":10}}
{ "title":"华为nova手机", "images":"http://image.jd.com/12479122.jpg", "price":2999, "stock": 300, "attr": { "category": "手机", "brand": "华为" } }

1.2. 匹配查询(match)

匹配所有

1
2
3
4
5
6
GET /mall/_search
{
"query":{
"match_all": {}
}
}
  • query:代表查询对象
  • match_all:代表查询所有

条件匹配

1
2
3
4
5
6
7
8
GET /mall/_search
{
"query": {
"match": {
"title": "小米手机"
}
}
}

查询出很多数据,不仅包括小米手机,而且与小米或者手机相关的都会查询到,说明多个词之间是or的关系。

某些情况下,我们需要更精确查找,我们希望这个关系变成and,可以这样做:

1
2
3
4
5
6
7
8
9
10
11
GET /mall/_search
{
"query": {
"match": {
"title": {
"query": "小米手机",
"operator": "and"
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"took" : 26,
"timed_out" : false,
"_shards" : {
"total" : 2,
"successful" : 2,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.7037868,
"hits" : [
{
"_index" : "atguigu",
"_type" : "goods",
"_id" : "1",
"_score" : 1.7037868,
"_source" : {
"title" : "小米手机",
"images" : "http://image.jd.com/12479122.jpg",
"price" : 1999,
"stock" : 200,
"attr" : {
"category" : "手机",
"brand" : "小米"
}
}
}
]
}
}

子属性匹配

1
2
3
4
5
6
7
8
GET /mall/_search
{
"query": {
"match": {
"attr.brand": "小米"
}
}
}

多字段匹配

match只能根据一个字段匹配查询,如果要根据多个字段匹配查询可以使用multi_match

1
2
3
4
5
6
7
8
9
GET /mall/_search
{
"query":{
"multi_match": {
"query": "小米",
"fields": ["title", "attr.brand.keyword"]
}
}
}

1.3. 词条查询(term)

term 查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些未分词的字符串。

1
2
3
4
5
6
7
8
GET /atguigu/_search
{
"query":{
"term":{
"price": 4999
}
}
}

1.4. 范围查询(range)

range 查询找出那些落在指定区间内的数字或者时间

1
2
3
4
5
6
7
8
9
10
11
GET /mall/_search
{
"query":{
"range": {
"price": {
"gte": 1000,
"lt": 3000
}
}
}
}

range查询允许以下字符:

操作符 说明
gt 大于
gte 大于等于
lt 小于
lte 小于等于

1.5. 布尔组合(bool)

布尔查询又叫组合查询

bool把各种其它查询通过must(与)、must_not(非)、should(或)的方式进行组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
GET /mall/_search
{
"query":{
"bool":{
"must": [
{
"range": {
"price": {
"gte": 1000,
"lte": 3000
}
}
},
{
"range": {
"price": {
"gte": 2000,
"lte": 4000
}
}
}
]
}
}
}

注意:一个组合查询里面只能出现一种组合,不能混用

1.6. 过滤(filter)

所有的查询都会影响到文档的评分及排名。如果我们需要在查询结果中进行过滤,并且不希望过滤条件影响评分,那么就不要把过滤条件作为查询条件来用。而是使用filter方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /mall/_search
{
"query": {
"bool": {
"must": {
"match": { "title": "小米手机" }
},
"filter": {
"range": {
"price": { "gt": 2000, "lt": 3000 }
}
}
}
}
}

注意:filter中还可以再次进行bool组合条件过滤。

1.7. 排序(sort)

sort 可以让我们按照不同的字段进行排序,并且通过order指定排序的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GET /mall/_search
{
"query": {
"match": {
"title": "小米手机"
}
},
"sort": [
{
"price": { "order": "desc" }
},
{
"_score": { "order": "desc"}
}
]
}

1.8. 分页(from/size)

1
2
3
4
5
6
7
8
9
10
GET /mall/_search
{
"query": {
"match": {
"title": "小米手机"
}
},
"from": 2,
"size": 2
}

from:从那一条开始

size:取多少条

1.9. 高亮(highlight)

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /mall/_search
{
"query": {
"match": {
"title": "小米"
}
},
"highlight": {
"fields": {"title": {}},
"pre_tags": "<em>",
"post_tags": "</em>"
}
}

fields:高亮字段

pre_tags:前置标签

post_tags:后置标签

1.10. 结果过滤(_source)

默认情况下,elasticsearch在搜索的结果中,会把文档中保存在_source的所有字段都返回。

如果我们只想获取其中的部分字段,可以添加_source的过滤

1
2
3
4
5
6
7
8
9
GET /atguigu/_search
{
"_source": ["title","price"],
"query": {
"term": {
"price": 2699
}
}
}

返回结果,只有两个字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"took" : 9,
"timed_out" : false,
"_shards" : {
"total" : 2,
"successful" : 2,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [
{
"_index" : "atguigu",
"_type" : "goods",
"_id" : "9",
"_score" : 1.0,
"_source" : {
"price" : 2699,
"title" : "vivo手机"
}
}
]
}
}