03.ElasticSearch高级检索

ElasticSearch高级检索

检索方式( _search)

ES官方提供了两中检索方式:一种是通过 URL 参数进行搜索,另一种是通过 DSL(Domain Specified Language) 进行搜索官方更推荐使用第二种方式第二种方式是基于传递JSON作为请求体(request body)格式与ES进行交互,这种方式更强大,更简洁

在这里插入图片描述

使用语法

URL查询: GET /索引/类型/_search?参数

DSL查询: GET /索引/类型/_search {}

准备工作

开始高级检索之前先来准备一下测试数据

1.删除索引
DELETE /christy

2.创建索引、映射与类型
PUT /christy
{
  "mappings": {
    "user":{
      "properties":{
        "name":{
          "type":"text"
        },
        "age":{
          "type":"integer"
        },
        "bir":{
          "type":"date"
        },
        "introduce":{
          "type":"text"
        },
        "address":{
          "type":"keyword"
        }
      }
    }
  }
}

3.批量插入数据
PUT /christy/user/_bulk
  {"index":{}}
  {"name":"Christy","age":20,"bir":"2001-01-01","introduce":"不要求很帅,像我这样就可以了","address":"京师"}
  {"index":{}}
  {"name":"Tide","age":23,"bir":"1998-09-08","introduce":"魔镜魔镜谁是世界上最美的女人","address":"开封"}
  {"index":{}}
  {"name":"hardy","age":5,"bir":"2016-02-12","introduce":"调皮捣蛋我最行","address":"杭州"}
  {"index":{}}
  {"name":"Tom","age":18,"bir":"2003-12-12","introduce":"Jerry是我最好的朋友","address":"纽约"}
  {"index":{}}
  {"name":"Jerry","age":6,"bir":"2015-10-10","introduce":"没有Tom的日子我真的好难过","address":"华盛顿"}
  {"index":{}}
  {"name":"布什","age":3,"bir":"2018-11-10","introduce":"我不是美国的那个总统,我只是一条普拉多,没有骂人的意思","address":"华盛顿"}

URL查询

1.查询所有(q=*)

语法:GET /index/type/_search?q=*。例如我想查询索引Christyuser类型的所有数据,可以这么写:

GET /christy/user/_search?q=*

在这里插入图片描述

上述结果可以看到该指令成功返回了查询结果,也符合我们的预期。对于返回结果中每个字段的意思如下图

在这里插入图片描述

2.按字段排序(sort)

语法:GET /index/type/_search?q=*&sort=fileName。比如上面查询出所有结果之后按年龄来排序,应该像下面这样:

GET /christy/user/_search?q=*&sort=age

在这里插入图片描述

3.分页查询(from&size)

语法:GET /index/type/_search?q=*&sort=fileName&size=count&from=(pageNumber-1)*size。例如:我想取出按年龄排序后结果中的前两天数据,应该像下面这样写

GET /christy/user/_search?q=*&sort=age&size=2&from=0

在这里插入图片描述

4.返回指定字段的查询结果(source)

语法:GET /index/type/_search?q=*&size=1&from=0&_source=filedName1,...。这个意思就是不需要返回每条记录的所有字段信息,比如我只想查询并返回用户的姓名和年龄,那么可以像下面这样写:

GET /christy/user/_search?q=*&size=1&from=0&_source=name,age

在这里插入图片描述

根据查询的返回结果我们可以看到只返回了我们定义的nameage两个字段的值

DSL查询

DSL查询是官方推荐的查询方式,相比较与URL,DSL能够根据更复杂的条件来查询,也是需要重点掌握的查询方式

1.查询所有(match_all)
GET /christy/user/_search
{
 	"query": { "match_all": {} }
}	

在这里插入图片描述

2.返回指定条数(size)
GET /christy/user/_search
{
 	"query": { "match_all": {} },
	"size": 2
}	

在这里插入图片描述

3.分页查询(from&size)
GET /christy/user/_search
{
  "query": {"match_all": {}},
  "size": 2, 
  "from": 1
}

在这里插入图片描述

from是从0开始的,上面的分页中我们从1开始取两条,就将第一条用户christy的数据给过滤掉了,返回结果的第一条数据应该是用户Tide

4.查询的结果集中返回指定字段(_source)
GET /christy/user/_search
{
  "query": {"match_all": {}},
  "size": 2, 
  "from": 1,
  "_source":["name","age"]
}

在这里插入图片描述

通过返回结果我们可以看到在上面分页结果的基础上只返回用户的name和age也是没有问题的。这里要注意的是命令中_source的参数是以数组的方式传递的

5.关键字查询(term)
GET /christy/user/_search
{
  "query": {
    "term": {
      "address": {
        "value": "开封"
      }
    }
  }
}

在这里插入图片描述

NOTE1: 通过使用term查询得知ES中默认使用分词器为标准分词器(StandardAnalyzer),标准分词器对于英文单词分词,对于中文单字分词

NOTE2: 通过使用term查询得知,在ES的Mapping Type 中 keyword , date ,integer, long , double , boolean or ip 这些类型不分词只有text类型分词

上面两条NOTE是什么意思呢?标准分词器将type类型为text的字段值分词后,只能按照单个汉字或者英文单词来查询,否则查询不到数据;比如我们测试数据的name类型是text,其中有一条名字叫做"布什"的普拉多,我们这个时候直接搜索布什是什么都搜索不到的,但是搜索单个的或者是可以找到这只可爱的普拉多的,就像下图演示的一样

在这里插入图片描述

6.范围查询(range)
GET /christy/user/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 8,
        "lte": 30
      }
    }
  }
}

在这里插入图片描述

上面我们看到的gtelte分别是大于等于小于等于的意思,上面的命令查询的是年龄大于等于8岁并且小于等于30岁的用户。如果需要查询大于8岁并且小于30岁的用户我们只需要把gte和lte改成gt和lt就行了;

7.前缀查询(prefix)
GET /christy/user/_search
{
  "query": {
    "prefix": {
      "content": {
        "introduce": "最"
      }
    }
  }
}

在这里插入图片描述

前缀查询关键字prefix用来检索含有指定前缀关键字的相关文档。比如上面我们查询introduce字段包含的用户。

8.通配符查询(wildcard)

通配符查询关键字wildcard说明:

?:用来匹配一个字符

*:用来匹配任意多个字符

GET /christy/user/_search
{
  "query": {
    "wildcard": {
      "introduce": {
        "value": "jerr*"
      }
    }
  }
}

在这里插入图片描述

NOTE:我们目前还没有配置分词器,ES用的是自带的标准分词器,一个汉字一个词,所以这里通配符查询不能测试汉字,只能测试英文。

9.多id查询(ids)

顾名思义,多id查询就是可以根据多个记录的id来查询多条记录。这个一般都是在实际应用中查询多个记录列表或者详情

GET /christy/user/_search
{
  "query": {
    "ids": {
      "values": ["OKEuB3kBVQPOYI_dp2GY","PKEuB3kBVQPOYI_dp2GY"]
    }
  }
}

在这里插入图片描述

10.模糊查询(fuzzy)
# fuzzy 模糊查询  最大模糊错误 必须在0-2之间
# 搜索关键词长度为 2 不允许存在模糊 0
# 搜索关键词长度为3-5 允许一次模糊 0 1 
# 搜索关键词长度大于5 允许最大2模糊
GET /christy/user/_search
{
  "query": {
    "fuzzy": {
      "introduce":"jerry"
    }
  }
}

首先,我们先演示第一种情况:搜索关键词长度为2,不允许存在模糊

在这里插入图片描述

address的类型是keyword不分词,我们输入京师是可以查到数据的,但是我们输入京湿查询不到的

现在我们来演示第二种情况:搜索关键字长度3-5,最大只允许一个模糊字符

在这里插入图片描述

按照introduce查找jerry是可以查询到数据的,我们改错一个字符也没有问题,但是改错两个字符就不行了

最后我们来演示最后一种情况,搜索关键字大于5时,最大只允许模糊两个字符,为此我们先准备一条数据

PUT /christy/user/_bulk
  {"index":{}}
  {"name":"ElasticSearch","age":20,"bir":"2001-01-01","introduce":"ElasticSearch是最牛逼的搜索的引擎","address":"china"}

然后我们就以elasticsearch为搜索关键字进行查询

在这里插入图片描述

效果如上图,这里就不解释了

11.布尔查询(bool)

bool关键字用来组合多个条件实现复杂查询,这也是bool查询的强大之处

must:相当于&&,同时成立

should:相当于||,满足一个条件就行

must_not:相当于!,不能满足任何一个

GET /christy/user/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "age": {
              "gte": 0,
              "lte": 30
            }
          }
        }
      ],
      "must_not": [
        {"wildcard": {
          "introduce": {
            "value": "jerr*"
          }
        }}
      ],
      "should": [
        {
          "term": {
            "age": {
              "value": "20"
            }
          }
        },
        {
          "term": {
            "introduce": {
              "value": "tom"
            }
          }
        }
      ]
    }
  }
}

在这里插入图片描述

12.高亮查询(highlight)

高亮关键字highlight可以让符合条件的文档中的关键字高亮,类似于下面这样

在这里插入图片描述

GET /christy/user/_search
{
  "query": {
    "term": {
      "introduce": {
        "value": "elasticsearch"
      }
    }
  },
  # highlight不是直接对结果进行高亮,而是对结果二次渲染高亮
  "highlight": {
  	# fields意思是对哪些字段匹配出来的结果进行高亮,虽然我们上面是查询introduce里面的elasticsearch,但是如果我们其他的字段比如‘name’中也有elasticsearch或者其他字段中也有,并且我们也希望高亮,那么我们像下面这样写成*即可
    "fields": {
      "*": {}
    }
  }
}

在这里插入图片描述

查询结果我们也看到了,ES确实将查询出来的关键字特别处理了,前后加上了,这是斜体的意思,如果我们想实现百度的那种加红处理,需要自定义pre_tagspost_tags

有人说上面的测试结果只把introduce里面查询出来的结果高亮了,name里面的没有高亮啊?那是因为没有加上require_field_match这个属性,他的意思是是否只开启查询字段高亮。属性值必须设置成false才能针对所有字段高亮

GET /christy/user/_search
{
  "query":{
    "term":{
      "introduce":"elasticsearch"
    }
  },
  "highlight": {
    "pre_tags": ["<span style='color:red'>"],
    "post_tags": ["</span>"],
    "require_field_match":false,
    "fields": {
      "*":{}
    }
  }
}

在这里插入图片描述

13.多字段查询(multi_match)
GET /christy/user/_search
{
  "query": {
    "multi_match": {
      "query": "tom",
      "fields": ["name","introduce"] #这里写要检索的指定字段
    }
  }
}

在这里插入图片描述

多字段查询需要注意

1.如果搜索的字段分词,他会对query进行先分词,后查询

2.如果搜索的字段部分词,他会直接使用query字符串整体进行搜索

在这里插入图片描述

我们使用tom纽约进行搜索,由于introducetext类型的,他是分词的;addresskeyword类型的部分词,所以在搜索introduce的时候先对query进行分词,而查询address的时候不分词,直接使用整体进行查询。所以在使用多字段查询的时候,查询的字段最好是分词的字段

14.多字段分词查询(query_string)

多字段分词查询顾名思义可以对查询关键字进行分词,而且可以指定分词器,就是这样一个牛逼的存在

GET /christy/user/_search
{
  "query": {
    "query_string": {
      "default_field": "introduce",
      "query": "tom和jerry"
    }
  }
}

在这里插入图片描述

当然们也可以像下面这样写

GET /christy/user/_search
{
  "query": {
    "query_string": {
      "fields": ["address","introduce"],
      "query": "tom和jerry"
    }
  }
}

在这里插入图片描述

这就实现了一个类似上面我们说的多字段查询。上面我们也说了这个可以指定分词器,可以像下面这样

GET /christy/user/_search
{
  "query": {
    "query_string": {
      "fields": ["address","introduce"],
      "query": "jerry华盛顿",
      "analyzer": "ik_max_word"
    }
  }
}

这里我们除了标准分词器还没有安装其他分词器,上面我们提到的ik_max_word下节我们再讲<( ̄▽ ̄)/

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

潮汐先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值