基本查询:
GET /索引库名/_search
{
"query":{
"查询类型":{
"查询条件":"查询条件值"
}
}
}
这里的
query
代表一个查询对象,里面可以有不同的查询属性
- 查询类型:
- 例如: match_all , match , term , range 等等
- 查询条件:查询条件会根据类型的不同,写法也有差异,后面详细讲解
查询所有(match_all)
GET /lagou/_search
{
"query":{
"match_all": {}
}
}
- query :代表查询对象
- match_all :代表查询所有
结果:
- took:查询花费时间,单位是毫秒
- time_out:是否超时
- _shards:分片信息
- hits:搜索结果总览对象
- total:搜索到的总条数
- max_score:所有结果中文档得分的最高分
- hits:搜索结果的文档对象数组,每个元素是一条搜索到的文档信息
- _index:索引库
- _type:文档类型
- _id:文档id
- _score:文档得分
- _source:文档的源数据
文档得分:使用
ES
时,对于查询出的文档无疑会有文档相似度之别。而理想的排序是和查询条件相关性越高排序越靠前,而这个排序的依据就是_score
匹配查询(match)
- or关系 :match 类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是or的关系
GET /lagou/_search
{
"query":{
"match":{
"title":"小米电视"
}
}
}
在上面的案例中,不仅会查询到电视,而且与小米相关的都会查询到,多个词之间是 or 的关系。
- and关系 :某些情况下,我们需要更精确查找:比如在电商平台精确搜索商品时,我们希望这个关系(查询条件切分词之后的关系)变成 and (既要满足你,又要满足我),可以这样做:
GET /lagou/_search
{
"query":{
"match":{
"title":{"query":"小米电视","operator":"and"}
}
}
}
本例中,只有同时包含 小米 和 电视 的词条才会被搜索到。
词条匹配(term)
term
查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些
未分词
的字符串,keyword
类型的字符串效果类似于:select * from tableName where colName='value';
GET /lagou/_search
{
"query":{
"term":{
"price":2699.00
}
}
}
结果:
布尔组合(bool)
bool
把各种其它查询通过
must
(与)、
must_not
(非)、
should
(或)的方式进行组合
GET /lagou/_search
{
"query":{
"bool":{
"must": { "match": { "title": "大米" }},
"must_not": { "match": { "title": "电视" }},
"should": { "match": { "title": "手机" }}
}
}
}
范围查询(range)
range
查询找出那些落在指定区间内的数字或者时间
GET /lagou/_search
{
"query":{
"range": {
"price": {
"gte": 1000.0,
"lt": 2800.00
}
}
}
}
range
查询允许以下字符:
操作符
|
说明
|
gt
| 大于 |
gte |
大于等于
|
lt
|
小于
|
lte
| 小于等于 |
模糊查询(fuzzy)
fuzzy
查询是
term
查询的模糊等价,很少直接使用它。
fuzzy
查询是
term
查询的模糊等价。它允许用户搜索词条与实际词条的拼写出现偏差,但是偏差的编辑距离不得超过2
:
GET /lagou/_search
{
"query": {
"fuzzy": {
"title": "appla"
}
}
}
结果过滤
默认情况下,
elasticsearch
在搜索的结果中,会把文档中保存在
_source
的所有字段都返回。如果我们只想获取其中的部分字段,我们可以添加 _source
的过滤
直接指定字段:
GET /lagou/_search
{
"_source": ["title","price"],
"query": {
"term": {
"price": 2699
}
}
}
指定
includes
和
excludes :
也可以通过:
- includes:来指定想要显示的字段
- excludes:来指定不想要显示的字段
二者都是可选的。
GET /lagou/_search
{
"_source": {
"includes":["title","price"]
},
"query": {
"term": {
"price": 2699
}
}
}
与下面的结果将是一样的:
GET /lagou/_search
{
"_source": {
"excludes": ["images"]
},
"query": {
"term": {
"price": 2699
}
}
}
过滤(filter)
Elasticsearch 使用的查询语言(DSL)拥有一套查询组件,这些组件可以以无限组合的方式进行搭配。 这套组件可以在以下两种情况下使用:过滤情况(filtering context)和查询情况(query context)。
如何选择查询与过滤:
通常的规则是,使用查询(query)语句来进行 全文 搜索或者其它任何需要影响 相关性得分 的搜索。除此以外的情况都使用过滤(filters)。
条件查询中进行过滤
所有的查询都会影响到文档的评分及排名。如果我们需要在查询结果中进行过滤,并且不希望过滤条件影响评分,那么就不要把过滤条件作为查询条件来用。而是使用 filter 方式:
GET /lagou/_search
{
"query":{
"bool":{
"must":{ "match": { "title": "小米手机" }},
"filter":{
"range":{"price":{"gt":2000.00,"lt":3800.00}}
}
}
}
}
无查询条件,直接过滤
如果一次查询只有过滤,没有查询条件,不希望进行评分,我们可以使用 constant_score 取代只有filter 语句的 bool 查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。
GET /lagou/_search
{
"query":{
"constant_score": {
"filter": {
"range":{"price":{"gt":2000.00,"lt":3000.00}}
}
}
}
}
排序
单字段排序 :
GET /lagou/_search
{
"query": {
"match": {
"title": "小米手机"
}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
多字段排序:
假定我们想要结合使用
price
和
_score
(得分) 进行查询,并且匹配的结果首先按照价格排序,然后按照相关性得分排序:
GET /lagou/_search
{
"query":{
"bool":{
"must":{ "match": { "title": "小米手机" }},
"filter":{
"range":{"price":{"gt":200000,"lt":300000}}
}
}
},
"sort": [
{ "price": { "order": "desc" }},
{ "_score": { "order": "desc" }}
]
}
分页
Elasticsearch
中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回。那么,如果要实现分页查询该怎么办呢?
elasticsearch
的分页与
mysql
数据库非常相似,都是指定两个值:
- from:目标数据的偏移值(开始位置),默认from为0
- size:每页大小
GET /lagou/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"price": {
"order": "asc"
}
}
],
"from": 3,
"size": 3
}
高亮
高亮原理:
- 服务端搜索数据,得到搜索结果
- 把搜索结果中,搜索关键字都加上约定好的标签
- 前端页面提前写好标签的CSS样式,即可高亮
elasticsearch
中实现高亮的语法比较简单:
GET /lagou/_search
{
"query": {
"match": {
"title": "手机"
}
},
"highlight": {
"pre_tags": "<em>",
"post_tags": "</em>",
"fields": {
"title": {}
}
}
}
在使用
match
查询的同时,加上一个
highlight
属性:
- pre_tags:前置标签
- post_tags:后置标签
- fields:需要高亮的字段
- title:这里声明title字段需要高亮