简介:Elasticsearch(ES)是一个开源的分布式搜索和分析引擎,用于快速存储、搜索和分析大量数据。它具有高性能、可扩展性和灵活性的特点,被广泛用于构建实时搜索、日志分析、数据可视化等应用。
这篇文章主要介绍检索相关的操作,单值、多值、范围、模糊等查询方式,使用bool支持多种条件复杂查询。
一、环境准备
版本
Docker version 20.10.22
elasticsearch:7.13.3
kibana:7.13.3
ps:具体启动命令参考第一篇ES博客
二、数据准备
下载官网测试数据
在ES官网中提供了简单的查询数据。点击下载示例数据 官方测试数据(bank)
使用postman导入到ES中
请求类型:POST
请求地址:http://127.0.0.1:9200/bank/account/_bulk?pretty
请求参数:binary类型,选择导入的json
Bank索引中的字段类型
执行命令GET bank/_mapping
查看bank索引的字段类型为 “text”,在ES中 “text” 类型用于存储长文本数据,并进行全文索引。
以address
字段为例,其类型为 “text”,其中也存在子字段为 “keyword” 的字段,类型为 “keyword”。“keyword” 类型用于存储关键字或短文本数据,通常用于精确匹配和排序操作。
通过定义子字段,可以在同一个字段上同时使用不同类型的分析器和查询方式。对于 “address” 字段,你可以使用 “text” 类型进行全文搜索,同时也可以使用 “keyword” 类型进行精确匹配和排序。
ps:使用方式为 address.keyword
在这个示例中, “keyword” 子字段还定义了 “ignore_above” 属性,它指定了该子字段中的值超过256个字符时将被截断。这可以用来限制关键字的长度,以便控制索引大小和提高检索性能。
{
"bank" : {
"mappings" : {
"properties" : {
"account_number" : {
"type" : "long"
},
"address" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
// 省略其他字段
}
}
}
}
四、标准查询
匹配单个字段
通过以下命令查询索引 bank 中,地址含有 place 字样的数据,返回了 181 条。
此字段为 text,查询时会进行分词匹配,像 282 Kings Place
会被ES进行分词,查询条件中含有分词后的单词,所以会被查出来。适合全文检索时使用。
其中 _score 返回值为匹配程度的一个得分,一定程度上讲,分值越大匹配越近似。
GET /bank/_search
{
"query": {
"match": {
"address": "place"
}
}
}
GET /bank/_search
{
"query": {
"term": {
"address": "place"
}
}
}
// 查询结果
"hits" : [
{
"_index" : "bank",
"_type" : "account",
"_id" : "20",
"_score" : 1.7070332,
"_source" : {
"account_number" : 20,
"balance" : 16418,
"firstname" : "Elinor",
"lastname" : "Ratliff",
"age" : 36,
"gender" : "M",
"address" : "282 Kings Place",
"employer" : "Scentric",
"email" : "elinorratliff@scentric.com",
"city" : "Ribera",
"state" : "WA"
}
},
精准匹配单个字段
上述查询在 address 后加上 keyword 的限制,那么这个字段就是 keyword 类型,只能进行精确查询,不再通过分词检索。age本身为数值型字段,不存在分词操作,查询全都是精确匹配。
GET /bank/_search
{
"query": {
"term": {
"address.keyword": "282 Kings Place"
}
}
}
GET /bank/_search
{
"query": {
"term": {
"age": "32"
}
}
}
多值匹配单个字段
使用 terms 命令,可以对字段进行多种关键词搜索,效果如同关系型数据库的 in 查询。
GET /bank/_search
{
"query": {
"terms": {
"age": [
"32",
"33",
"34"
]
}
}
}
范围查询
使用 range 关键词。参数含义如下
- gt - 大于 ( > )
- gte - 大于且等于 ( >= )
- lt - 小于 ( < )
- lte - 小于且等于 ( <= )
GET /bank/_search
{
"query": {
"range": {
"age": {
"gte": 32,
"lte": 33
}
}
}
}
模糊查询
模糊查询有多重方式,这里介绍两种,一种是模糊,一种是正则
GET /bank/_search
{
"query": {
"wildcard": {
"firstname": {
"value": "am*"
}
}
}
}
四 、Bool组合查询
在ES中bool查询就是用来组合布尔查询条件,布尔查询条件,就是类似SQL中的and 、or 。
下面是一个复合查询语句,分别使用了must
、filter
、must_not
、should
。下面的语句相当于SQL
SELECT
*
FROM
bank
WHERE
gender = "M"
AND state = "IA"
AND city != "Healy"
OR ( age = 39 OR age = 21)
POST bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"gender.keyword": "M"
}
}
],
"filter": [
{
"match": {
"state.keyword": "IA"
}
}
],
"must_not": [
{
"match": {
"city.keyword": "Healy"
}
}
],
"should": [
{
"match": {
"age": "39"
}
},
{
"match": {
"age": "21"
}
}
]
}
},
"from": 0,
"size": 10,
"sort": [
{
"firstname.keyword": {
"order": "desc"
}
}
],
"aggs": {}
}
查询关键词 Query Action
- 布尔查询:must,must_not,should等。类似SQL的and,or,! 等
- 匹配查询:match multi_match等。类似SQL的like
- 范围查询:range。类似SQL的大于,小于,等于
- term查询:term。类似SQL的 “=”
- 正则查询:regex 正则
- exists和missing查询:类似于SQL is null,is not null
查询语法总结
- 最外层为query
- 单重条件查询只需在 query 写入条件,复合查询条件包含在bool对象中
分页查询
from、size 分别对应 page 和 pageSize
排序
排序的写法就如一个对象,对象的 key 为字段名,value为排序规则,当然是可以多字段一起排序的,写入多个即可
查询关键词与分数关系
must | must查询是必要条件,必须满足。参与相关性评分 |
---|---|
filter | 与must类似,同样必须满足。不参与相关性评分,但结果集会被缓存 |
should | 如果只有一个 should 子句情况下与 must 子句结果一样,如果有多个should子句情况下,命中任何一个即可 |
must_not | 与must类似,同样必须不满足。不参与相关性评分,但结果集会被缓存 |
五、总结
- 在ES中,如同普通SQL语句都有着类似API可以调用。
- ES支持对内容进行分词,根据分词进行搜索,并对结果进行打分。适合对文章内容进行搜索,而关系型数据库例如 MySQL,对这个功能支持能力不强。
- 查询语句在query内层套用 bool,可以支持多种条件过滤,同时也可以计算得分。