6.3 基于es api进行查询的注意事项

  • 此文档记录一些初次使用elasticsearch进行开发时,经常遇到的问题,请在阅读完此文档后再开始你的第一次查询

目录

[TOC]

说明与须知

  • es集群属于公共资源,如果进行不合理查询影响到集群稳定性,会在第一时间禁用使用权限并警告

  • kibana同样只是一个使用es api的查询工具,只不过做了许多默认查询限制,如右上角的时间区间,每次搜索前的选择索引.正是这些限制条件,可以尽可能的减少查询耗时,优化查询效率.开发者在使用api进行查询时,同样需要这些限制,尽可能优化查询条件

  • 推荐使用DevTools进行查询语句的调试

es查询入门文档

Request Body Search

禁止直接使用/_search进行查询

直接使用/_search接口进行查询时,会对全部可查询的(一般指具有权限权限的)索引进行查询,造成巨大的查询压力,所以务必不要直接请求/_search接口

推荐指定索引进行查询,索引可以使用*将索引名称中的日期进行通配处理,查询时间区间使用下文中提到的range进行限制

POST /logstash-consumer.v2-javastack-prod-*/_search

务必带有range条件

  • 不等查询时间区间进行声明,默认会对全部时间范围内进行查询,造成巨大的查询压力

  • 推荐使用时间戳(如@timestamp)进行查询时间区间限制,以下为使用毫秒时间戳进行查询的示例

  • 如果使用自定义字段进行时间范围限制,一定注意检查此字段是否在es中被识别为date类型

{
    "query": {
        "bool": {
            "must": [
                {
                    "query_string": {
                        ···
                    }
                },
                {
                    "range": {
                        "@timestamp": {
                            "from": 1554241298349,
                            "to": 1554255698349,
                            "include_lower": false,
                            "include_upper": true,
                            "format": "epoch_millis",
                            "boost": 1
                        }
                    }
                }
            ]
        }
    }
}

尽量避免使用wildcard或通配符查询

wildcard类似mysql中的like,用起来方便但是效率并不高,查询过程中不会使用分词器

在使用wildcard查询时,应杜绝使用通配符,号打头(如`ServiceException`),这种形式的查询会造成查询效率低下.原因是:为了加速通配符和正则表达式的匹配速度,Lucene4.0开始会将输入的字符串模式构建成一个DFA (Deterministic Finite Automaton),带有通配符的pattern构造出来的DFA可能会很复杂,开销很大

在不得已使用的情况下,需要对查询条件的长度进行约束,如果首尾通配符中间是很长的一个字符串,会造成对应的wildcard Query执行非常慢及消耗大量CPU,可能导致整个集群无响应

增加查询超时时间

在大部分合理请求的情况下,es可实现毫秒级响应,所以在调试查询api时,推荐使用超时时间限制,避免误操作或突发大量数据造成es集群压力骤增,影响他人使用 推荐设置的超时时间为5s,一般可满足大部分查询场景

POST /logstash-nginx-2019.04.02/_search?timeout=5s

或者添加在查询条件中:

{ 
    "timeout":"5s",
    "query": {
        ...
    }
}

使用query-bool-filter组合取代普通query进行查询

默认情况下,es通过一定的算法计算返回的每条数据与查询语句的相关度,并通过_score字段来表征.但对于非全文索引的使用场景,用户并不关心查询结果与查询条件的相关度,只是想精确的查找目标数据.此时,可以通过query-bool-filter组合来让es不计算_score,并且尽可能的缓存filter的结果集,供后续包含相同filter的查询使用,提高查询效率

# 普通查询
POST my_index/_search
{
  "query": {
    "term" : { "user" : "Kimchy" } 
  }
}

# query-bool-filter 加速查询
POST my_index/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": { "user": "Kimchy" }
      }
    }
  }
}

一些查询情景示例

查询并根据字段去重,得到去重后的数量

查询语句

POST /logstash-consumer-nginx-2019.04.09/_search
{
    "query": {
        "bool": {
            "must": [
                {
                    "wildcard": { //通配符查询,或替换为其他查询方式
                        "request": "*\/\/platform*"
                    }
                },
                {
                    "range": { //指定时间区间,或用其它方式指定
                        "@timestamp": {
                            "gte": "now-1d/d",
                            "lte": "now/d",
                            "time_zone": "+08:00"
                        }
                    }
                }
            ]
        }
    },
    "aggs": {
        "request_aggs_num": {
            "cardinality": { //聚合并得到基数
                "field": "url" //指定url字段为聚合字段
            }
        }
    },
    "size": 0, // 返回query的结果详情,一般不需要,设置为0
    "from": 0
}

返回结果

{
  "took" : 1429, //花费时间(ms)
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 346108, //查询到的总结果数量
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "request_aggs_num" : {
      "value" : 33 //得到的去重后的结果数量
    }
  }
}

查询并根据字段去重,得到去重后的详细值

查询语句

{
    "query": {
        ···
    },
    "aggs": {
        "request_aggs": {
            "terms": {
                "field": "url",
                "size": 100 // 显示数量最多的前100条内容,根据上文中的匹配结果酌情设置
            }
        }
    }
}

返回结果

{
  "took" : 733,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 346108,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "request_aggs" : {
      "doc_count_error_upper_bound" : 39,
      "sum_other_doc_count" : 8600,
      "buckets" : [ // 显示聚合后的字段详情及数量
        {
          "key" : "/platform/repayment/batch_update",
          "doc_count" : 265458
        },
        {
          "key" : "/platform/sms/sendSMSCodeNew",
          "doc_count" : 66325
        },
        {
          "key" : "/platform/primeloans/customer/device/save",
          "doc_count" : 5725
        }
      ]
    }
  }
}

查询结果并根据拼接字段去重,得到去重后的详细值

查询语句

{
    "query": {
        ···
    },
    "aggs":{
        "uniq_url_aggs":{
            "terms":{
                "script":"doc['domain'].value + doc['url'].value",
                "size":200
            }
        }
    }
}

查询结果并进行多重聚合

查询语句

{
    "query": {
        ···
    },
    "aggs":{
        "domain_aggs":{
            "aggs":{
                "uniq_url_aggs":{
                    "terms":{
                        "field":"url",
                        "size":5
                    }
                }
            },
            "terms":{
                "field":"domain",
                "size":3
            }
        }
    }
}

返回结果

{
  "took" : 190,
  "timed_out" : false,
  "_shards" : {
    "total" : 34,
    "successful" : 34,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1556,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "domain_aggs" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 1,
      "buckets" : [
        {
          "key" : "www.shanshanhua.com",
          "doc_count" : 1548,
          "uniq_url_aggs" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "/platform/wechatsign/getAccessToken",
                "doc_count" : 1548
              }
            ]
          }
        },
        {
          "key" : "m.net",
          "doc_count" : 5,
          "uniq_url_aggs" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "/platform/wechatsign/getAccessToken",
                "doc_count" : 5
              }
            ]
          }
        },
        {
          "key" : "cashmall.net",
          "doc_count" : 2,
          "uniq_url_aggs" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "/risk/queryOrderDetail",
                "doc_count" : 2
              }
            ]
          }
        }
      ]
    }
  }
}

最后更新于