kibana查询

212 阅读6分钟

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

基本查询

基本语法

GET /索引库名/_search
{
    "query":{
        "查询类型":{
            "查询条件":"查询条件值"
        }
    }
}

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

  • 查询类型:
    • 例如:match_all,match,term,range等等
  • 查询条件:查询条件会根据类型的不同,写法也有差异

查询所有(match_all)

GET /lagou/_search
{
    "query":{
        "match_all": {}
    }
}
  • query:代表查询对象
  • match_all:代表查询所有

结果:

{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 1,
        "hits": [
            {
                "_index": "lagou",
                "_type": "goods",
                "_id": "2",
                "_score": 1,
                "_source": {
                    "title": "大米手机",
                    "images": "http://image.lagou.com/12479122.jpg",
                    "price": 2899
                }
             },
             {
                "_index": "lagou",
                "_type": "goods",
                "_id": "r9c1KGMBIhaxtY5rlRKv",
                "_score": 1,
                "_source": {
                    "title": "小米手机",
                    "images": "http://image.lagou.com/12479122.jpg",
                    "price": 2699
                }
            }
        ]
    }
}
  • took:查询花费时间,单位是毫秒
  • time_out:是否超时
  • _shards:分片信息
  • hits:搜索结果总览对象
    • total:搜索到的总条数
    • max_score:所有结果中文档得分的最高分
    • hits:搜索结果的文档对象数组,每个元素是一条搜索到的文档信息
      • _index:索引库
      • _type:文档类型
      • _id:文档id
      • _score:文档得分
      • _source:文档的源数据

文档得分:使用ES时,对于查询出的文档无疑会有文档相似度之别。而理想的排序是和查询条件相关性越高排序越靠前,而这个排序的依据就是_score

匹配查询(match)

先加入一条数据,便于测试:

PUT /lagou/goods/3
{
    "title":"小米电视4A",
    "images":"http://image.lagou.com/12479122.jpg",
    "price":3899.00
}

现在,索引库中有2部手机,1台电视:

  • 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查询的模糊等价,很少直接使用它。

新增一个商品:

POST /lagou/goods/5
{
    "title":"apple手机",
    "images":"http://image.lagou.com/12479122.jpg",
    "price":6899.00
}

fuzzy查询是term查询的模糊等价。它允许用户搜索词条与实际词条的拼写出现偏差,但是偏差的编辑距离不得超过2:

GET /lagou/_search
{
    "query": {
        "fuzzy": {
            "title": "appla"
        }
    }
}

上面的查询,也能查询到apple手机

image.png

结果过滤

默认情况下,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
        }
    }
}

过滤(fifilter)

Elasticsearch 使用的查询语言(DSL)拥有一套查询组件,这些组件可以以无限组合的方式进行搭配。这套组件可以在以下两种情况下使用:过滤情况(fifiltering context)和查询情况(query context)。

如何选择查询与过滤:

通常的规则是,使用查询(query)语句来进行 全文 搜索或者其它任何需要影响 相关性得分 的搜索。除此以外的情况都使用过滤(fifilters)。

条件查询中进行过滤

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

GET /lagou/_search
{
    "query":{
        "bool":{
            "must":{ "match": { "title": "小米手机" }},
            "filter":{
                "range":{"price":{"gt":2000.00,"lt":3800.00}}
            }
        }
    }
}

无查询条件,直接过滤

如果一次查询只有过滤,没有查询条件,不希望进行评分,我们可以使用constant_score取代只有fifilter语句的bool查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。

GET /lagou/_search
{
    "query":{
        "constant_score": {
            "filter": {
                "range":{"price":{"gt":2000.00,"lt":3000.00}}
            }
        }
    }
}

排序

单字段排序

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

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:后置标签
  • fifields:需要高亮的字段
    • title:这里声明title字段需要高亮