欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES(三)es查询语法

程序员文章站 2022-07-06 15:47:53
...

一、介绍:语法GET /索引/类型/_search         查询条件,这个查询条件有两种写法,

  一种是在GET的url中指定参数:这种方法比较简单,如查询所有

GET /wtyy-test/user/_search

   条件查询: 

GET /es-test/_search?q=blog

  分页查询:

GET /es-test/_search?size=5&from=10

还有一种是ES查询表达式 (DSL) 检索:将请求参数按照ES约定的格式构造为一个JSON进行请求,放在请求体中。下面重点来看下:

 1、查询条件:封装在query中,常用的查询方式有:

查询方式

含义

使用方法

备注

term过滤

term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串。

not_analyzed 的字符串:未经切词的文本数据类型。

  1. {

  2. "query": {

  3. "term": {

  4. "title": "内蒙古"

  5. }

  6. }

  7. }

 

terms过滤

terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么document需要一起去做匹配。

  1. {

  2. "query": {

  3. "terms": {

  4. "title": [

  5. "内蒙古",

  6. "黑龙江"

  7. ]

  8. }

  9. }

  10. }

 

range

range过滤允许我们按照指定范围查找一批数据。

  1. {

  2. "query":{

  3. "range": {

  4. "pubTime": {

  5. "gt": "2017-06-25",

  6. "lt": "2017-07-01"

  7. }

  8. }

  9. }

  10. }

范围操作符包含:

关键字

含义

gt

大于

gte

大于等于

lt

小于

lte

小于等于

exists和missing

exists 和 missing 过滤可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的IS_NULL条件。

这两个过滤只是针对已经查出一批数据来,但是想区分出某个字段是否存在的时候使用。

  1. {

  2. "exists":{

  3. "field":"title"

  4. }

  5. }

 

bool过滤

bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:

must :: 多个查询条件的完全匹配,相当于 and。

must_not :: 多个查询条件的相反匹配,相当于 not。

should :: 至少有一个查询条件匹配, 相当于 or。

这些参数可以分别继承一个过滤条件或者一个过滤条件的数组

  1. {

  2. "bool":{

  3. "must":{

  4. "term":{

  5. "folder":"inbox"

  6. }

  7. },

  8. "must_not":{

  9. "term":{

  10. "tag":"spam"

  11. }

  12. },

  13. "should":[

  14. {

  15. "term":{

  16. "starred":true

  17. }

  18. },

  19. {

  20. "term":{

  21. "unread":true

  22. }

  23. }

  24. ]

  25. }

  26. }

2、排序:封装在sort中 。

二、DSL检索:

1、简单查询:

 1)查询所有结果:

GET /wtyy-test/user/_search
{
    "query":{"match_all":{}}
}

 2)条件查询:post_filter  和 query 的 区别 ,语法上没区别,唯一的在于 filter 不评分,所以 filter  比 query  快很多 ,filter 和query  可以共存。

GET /wtyy-test/user/_search
{
    "query":{
          "match":{
                    "name":"李四"
          }
    },
    "sort":[
        {
             "age":"desc"
       }
   ]
}

 3)范围查询:

GET /wtyy-test/user/_search
{
    "query":{
      "range": {
        "age": {
          "gte": 18,
          "lte": 20
        }
      }
    }
  
}

  4)指定查询结果的字段 _source

GET /wtyy-test/user/_search
{
    "query":{"match_all":{}},
    "_source":["name","age"]
}

5)多条件的复合查询bool : bool 里面的都是一些条件 ,must 必须瞒足,should 只要满足 minimum_should_match 个条件是ture ,filter只是过滤不计入评分。

GET /wtyy-test/user/_search
{
	"query": {
		"bool": {
			"must": [{
				"match": {
					"name": "李四"
				}
			}],
			"should": [{
					"match": {
						"age": 18
					}

				},
				{
					"match": {
						"address": "重庆"
					}

				}
			],
			"minimum_should_match": 1

		}
	}
}

查询结果:

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 1.5162321,
    "hits": [
      {
        "_index": "wtyy-test",
        "_type": "user",
        "_id": "AXVuJKSiQnB0qZbmUT7E",
        "_score": 1.5162321,
        "_source": {
          "name": "李四",
          "age": 18
        }
      },
      {
        "_index": "wtyy-test",
        "_type": "user",
        "_id": "AXVuQymtQnB0qZbmUT7G",
        "_score": 1.5162321,
        "_source": {
          "name": "李四",
          "age": 18,
          "address": "上海"
        }
      },
      {
        "_index": "wtyy-test",
        "_type": "user",
        "_id": "AXVuBYO2QnB0qZbmUT69",
        "_score": 1.0324643,
        "_source": {
          "name": "李四",
          "age": 20,
          "address": "重庆"
        }
      }
    ]
  }
}

 2、分页查询:对于查询得到的结果,数目过多的情况下,es 默认会进行分页。分页主要有两个参数进行控制: size 显示应该返回的结果数量,默认是 10 ;from 显示应该跳过的初始结果数量,默认是 0。

GET /wtyy-test/user/_search
{
  "query":{
    "match": {
        "name": "李四"
    }
  },
  "size": 10,
  "from": 1
}

3、聚合函数:

1)求平均值:

GET  wtyy-test/user/_search
{
  "query": {
    "match": {"name":"李四"}
  },
  "aggs": {
    "total_count": {
      "value_count": {
        "field": "age"
      }
    },
    "pjz":{
      "avg": {
        "field": "age"
      }
    }
    
  }
  
}

  返回结果:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 1.4252472,
    "hits": [
      {
        "_index": "wtyy-test",
        "_type": "user",
        "_id": "AXVuQymtQnB0qZbmUT7G",
        "_score": 1.4252472,
        "_source": {
          "name": "李四",
          "age": 18,
          "address": "上海"
        }
      },
      {
        "_index": "wtyy-test",
        "_type": "user",
        "_id": "AXVuJKSiQnB0qZbmUT7E",
        "_score": 1.0754046,
        "_source": {
          "name": "李四",
          "age": 18
        }
      },
      {
        "_index": "wtyy-test",
        "_type": "user",
        "_id": "AXVuBYO2QnB0qZbmUT69",
        "_score": 0.51623213,
        "_source": {
          "name": "李四",
          "age": 20,
          "address": "重庆"
        }
      }
    ]
  },
  "aggregations": {
    "pjz": {
      "value": 18.666666666666668
    },
    "total_count": {
      "value": 3
    }
  }
}

  4、分组:

GET  wtyy-test/user/_search
{
  "query": {
    "match": {"name":"李四"}
  },
  "aggs": {
    "fz": {
      "terms": {
        "field": "age"
      }
    }
  }
  
}

5、 scoll 游标查询,指定 scroll=时间 ,指定保存的分钟数,第一次发起请求放回的不是数据,而是 _scroll_id ,后面通过 _scroll_id 去请求数据,非常适合大批量查询。

get /user/student/_search?scroll=1m
{
    "query":{
      "match_all": {}
    },
    "size":2
  
}
GET /_search/scroll
{
    "scroll": "1m",
    "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAIuFkRMbVZ0WFdvU1ZHWEJuelFIQk4tdFEAAAAAAAACLBZETG1WdFhXb1NWR1hCbnpRSEJOLXRRAAAAAAAAAi0WRExtVnRYV29TVkdYQm56UUhCTi10UQAAAAAAAAO1FlQwSkJqVng5UVpPUTIwbWw0a0NKV3cAAAAAAAADthZUMEpCalZ4OVFaT1EyMG1sNGtDSld3"
}

 游标 查询 是在 es 里面缓存了结果 ,然后一次 一次的去取 所以发起 第一次请求的时候只有 size ,没有from ,后面的 请求只有 scroll_id 和  scroll 时间

6、关键词高亮显示:

通常自己开发搜索引擎的时候,往往需要对搜索结果中的关键词高亮这种功能。请求体增加一个 highlight 属性,里面指明要高亮的字段。如下:

GET  wtyy-test/user/_search
{
  "query": {
    "match": {
      "address": "北京"
    }
  },
  "highlight": {
    "fields": {
      "address": {}
    }
  }
}

返回消息体如:

{
  "took": 61,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.7787034,
    "hits": [
      {
        "_index": "wtyy-test",
        "_type": "user",
        "_id": "1",
        "_score": 0.7787034,
        "_source": {
          "name": "王五1",
          "age": 1,
          "address": "湖北",
          "school": "测试学校"
        },
        "highlight": {
          "address": [
            "湖<em>北</em>"
          ]
        }
      }
    ]
  }
}

在返回体中有一个 highlight 字段,里面对 message 字段进行高亮处理: 关键词使用了 <em></em> 标签包围了。可以使用 css 修改对 <em> 标签的样式,以实现关键词高亮效果。

7、多索引查询:在多个索引中同时搜索文档,把多个索引看做一个使用。其实这也意味着,我们在存储的时候,没必要把所有的文档都存在一个 Index 中。 很常见的一个操作是,我们可以将文档按天分索引存储。例如: es-test-2020-03-11,es-test-2020-03-12 等, 在查询的时候,指定 es-test-* 查询即可,这样对外看来,文档似乎还是存储在一起,同时也减轻了 Index 的存储压力。(一个 ES 分片最多能存储 Integer.MAX_VALUE - 128 个文档)

GET /es-test-1,es-test-2/_search
GET /es-test-*/_search
GET /a*, b*/_search

8、批查询 api mget:

#批量查询
GET /_mget
{
  "docs":[
    {
      "_index":"user",
      "_type":"student",
      "_id":1
    },
    {
      "_index":"user",
      "_type":"student",
      "_id":2
    },
    {
      "_index":"user",
      "_type":"student",
      "_id":2
    }
  ]
}

 mget  如果请求url 里面有 index 和 type 后面 的 请求体里面就可以不写  index 和type

9、es的 并发处理 ,使用的乐观锁 在 后面加上 version:

POST  /user/student/1?version=3
{
  "name":"zyk",
  "age":0
}

 只有version = 当前记录的version的时候才能修改成功。es 可以自动控制 vserion 通过 ,version_type指定 ,version_type=external 要求 version 大于当前的version ,version_type=internal 这个是默认值 ,必须等于当前的值<br>version_type=external_gte 大于等于当前的version<br>version_type=force 已经废弃了不能用了,我也不知道以前什么意思,提升, Validation Failed: 1: version type [force] may no longer be used

POST  /user/student/1?version_type=external&version=505
{
  "name":"zyk",
  "age":0
}

三、动态映射

有一点值得注意的是,本文中的例子都是用了 message 字段来进行 match 搜索,如果换成字段名换成了其他,例如 content 可能就不行。这是因为在我这边的 ES 有一个默认的动态映射,将长度低于 2048 的字符串认定为 keyword 类型。但是字段名是 message 的话,则为 text 类型。keyword 类型不进行分词处理,不适合进行关键词搜索处理。这样就需要我们不得不关注 ES 的动态映射。此部分内容以后会再单独分一篇文章讲解。

相关标签: Elasticsearch