前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >es各种查询

es各种查询

作者头像
爱撒谎的男孩
发布2019-12-31 15:38:52
6.6K0
发布2019-12-31 15:38:52
举报
文章被收录于专栏:码猿技术专栏码猿技术专栏

文章目录

1. 请求体查询

1.1. 简单查询 【不推荐】

1.2. 空查询

1.3. 精确值查找

1.3.1. term查询

1.3.1.1. 实例

1.3.1.1.1. 查询数值

1.3.1.1.2. 查询文本

1.3.1.1.2.1. 解决

1.3.2. terms

1.4. 指定文档数量 (from ,size)

1.5. 返回指定的字段 _source

1.6. 返回版本号

1.7. match查询

1.8. match_all

1.9. match_phrase

1.10. 排序

1.11. range

1.11.1. 日期查询

1.11.2. 数字

1.11.3. 字符串范围

1.12. wildcard查询

1.13. 模糊查询 fuzzy

1.14. 高亮查询

1.15. null值的查询

1.16. filter查询

1.16.1. 简单的过滤查询

1.16.2. bool过滤查询

1.16.2.1. 实例

1.16.3. 嵌套bool过滤查询

1.16.4. 范围过滤

1.16.5. 非空的过滤查询

1.17. 聚合查询

请求体查询

简单查询 【不推荐】

空查询

1、GET /lib/user/_search : 查询lib索引下的user类型的全部数据

2、GET /lib/_search :查询lib索引下的全部类型的数据

3、GET /_search :查询全部索引下的数据

精确值查找

  • 当进行精确值查找时, 我们会使用过滤器(filters)。过滤器很重要,因为它们执行速度非常快,不会计算相关度(直接跳过了整个评分阶段)而且很容易被缓存。我们会在本章后面的 过滤器缓存 中讨论过滤器的性能优势,不过现在只要记住:请尽可能多的使用过滤式查询。

term查询

  • elasticsearch对这个搜索的词语不做分词,用于精确匹配,比如Id,数值类型的查询。
  • 可以用它处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。
实例
  • 批量插入数据
    • 没有手动插入映射,因此ElasticSearch会为我们自动创建映射,这就意味着只要是文本就会为我们使用分词器分词。
代码语言:javascript
复制
POST /my_store/products/_bulk
{ "index": { "_id": 1 }}
{ "price" : 10, "productID" : "XHDK-A-1293-#fJ3" }
{ "index": { "_id": 2 }}
{ "price" : 20, "productID" : "KDKE-B-9947-#kL5" }
{ "index": { "_id": 3 }}
{ "price" : 30, "productID" : "JODL-X-1937-#pV7" }
{ "index": { "_id": 4 }}
{ "price" : 30, "productID" : "QQPX-R-3956-#aD8" }
查询数值
  • 使用constant_score查询以非评分模式来执行 term 查询并以一作为统一评分,这样返回的结果的评分全部是1
  • 使用constant_score将term转化为过滤器查询
代码语言:javascript
复制
GET /my_store/products/_search
{
    "query" : {
        "constant_score" : { 
            "filter" : {
                "term" : { 
                    "price" : 20
                }
            }
        }
    }
}

//结果如下
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "my_store",
        "_type": "products",
        "_id": "2",
        "_score": 1,
        "_source": {
          "price": 20,
          "productID": "KDKE-B-9947-#kL5"
        }
      }
    ]
  }
}
查询文本
  • 文本怎样分词
    • 大写字母转换为小写字母
    • 复数变成单数
    • 去掉特殊字符
  • 由于term是精确查询,但是在查询文本的时候,很有可能这个文本已经进行了分词,但是term查询的时候搜索的词不分词,因此可能两个文本明明是一样的,但是却匹配不上。
代码语言:javascript
复制
GET /my_store/products/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "term" : {
                    "productID" : "XHDK-A-1293-#fJ3"   //虽然和插入的数据一样,但是却查询不到
                }
            }
        }
    }
}
  • 从上面的结果可以看到,由于term查询默认是不对搜索的词进行分词的,但是在查询的文本是分词的,因此这里肯定是查询不到的,我们可以使用分词分析器看看这个productID如何实现分词的,如下:
代码语言:javascript
复制
GET /my_store/_analyze
{
  "field": "productID",    //指定分词的域
  "text": "XHDK-A-1293-fJ3-the"    //文本内容
}


//结果如下:
{
  "tokens": [
    {
      "token": "xhdk",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "a",
      "start_offset": 5,
      "end_offset": 6,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "1293",
      "start_offset": 7,
      "end_offset": 11,
      "type": "<NUM>",
      "position": 2
    },
    {
      "token": "fj3",
      "start_offset": 12,
      "end_offset": 15,
      "type": "<ALPHANUM>",
      "position": 3
    },
    {
      "token": "the",
      "start_offset": 16,
      "end_offset": 19,
      "type": "<ALPHANUM>",
      "position": 4
    }
  ]
}
  • 从上面的结果可知:
    • 在分词的过程中自动去掉了特殊字符,比如-&
    • 大写字母全部转为小写
解决
  • 如果需要使用term精确匹配查询文本,那么这个文本就不能使用分词器分词,因此需要手动创建索引的映射(mapping),如下:
代码语言:javascript
复制
DELETE my_store   //先删除索引

PUT /my_store    //手动指定映射
{
    "mappings" : {
        "products" : {
            "properties" : {
                "productID" : {
                    "type" : "string",
                    "index" : "not_analyzed"    //不分词
                }
            }
        }
    }

}
  • 此时如果再查询,那么就会精确匹配到这个信息了。

terms

  • 对于多个关键字的查询,假设我们需要查询price在10,20,30中的其中一个即可,那么需要使用terms指定多组值
  • 精确查询,不会使用分词器
代码语言:javascript
复制
GET /my_store/products/_search
{
    "query":{
      "terms":{
        "price":[20,10,30]
      }
    }
}

指定文档数量 (from ,size)

  • 假设我们需要对前两个文档进行查询,那么可以使用fromsize指定文档的数量,如下:
代码语言:javascript
复制
GET /my_store/products/_search
{
  "from":0,    //从第一文档开始
  "size":2,     //查询两个文档
    "query":{
      "terms":{
        "price":[20,10,30]
      }
    }
}

返回指定的字段 _source

  • 在使用查询的时候默认返回的是全部的字段,那么我们可以使用_source指定返回的字段
代码语言:javascript
复制
GET /lib/user/_search
{
  "_source":["address","age"], 
  "query": {
    "match_phrase": {
      "address": "huibei,wuhan"
    }
  }
}
  • 同时我们也可以排除不返回哪些字段,使用exclude即可
代码语言:javascript
复制
GET /lib/user/_search
{
  "_source":{
    "exclude": ["address","age"],   //排除字段
    "include": ["name","date"]   //包含的字段
  },
  "query": {
    "match_phrase": {
      "address": "huibei,wuhan"
    }
  }
}

返回版本号

  • 默认的查询返回版本号,我们可以在查询体中加上version:true即可
代码语言:javascript
复制
GET /my_store/products/_search
{
  "version":true, 
  "from":0,
  "size":2,
    "query":{
      "terms":{
        "price":[20,10,30]
      }
    }
}

match查询

  • match查询和term查询相反,知道分词器的存在,会对搜索的词语进行分词。
  • 上面使用match查询productId的时候,因为terms不知道分词器的存在,因此查询不到,但是我们使用match查询可以匹配到,如下:
代码语言:javascript
复制
GET /my_store/products/_search
{
    "query" : {
                "match" : {
                    "productID" : "XHDK-A-1293-#fJ3"
            }
    }
}
  • 比如说我们要查找姓名是zhaoliu或者zhaoming的,那么只需要使用match即可
代码语言:javascript
复制
GET /my_store/products/_search
{
    "query" : {
                "match" : {
                    "name" : "zhaoliu zhaoming"  //会对这个短语进行分词,分出两个,之后去查询
            }
    }
}

match_all

  • 查询所有
代码语言:javascript
复制

GET /my_store/products/_search
{
  "query": {
    "match_all": {
  
    }
  }
}

match_phrase

  • 短语匹配查询
  • 类似 match 查询, match_phrase 查询首先将查询字符串解析成一个词项列表,然后对这些词项进行搜索,但只保留那些包含 全部 搜索词项,且 位置 与搜索词项相同的文档。 比如对于 quick fox 的短语搜索可能不会匹配到任何文档,因为没有文档包含的 quick 词之后紧跟着 fox
  • 位置顺序必须一致
代码语言:javascript
复制
GET /lib/user/_search
{
  "query": {
    "match_phrase": {
      "address": "huibei,wuhan"
    }
  }
}

排序

  • 使用sort可以进行排序
代码语言:javascript
复制
GET /lib/user/_search
{
  "_source":{
    "exclude": ["address","name"],
    "include": ["age","date"]
  },
  "query": {
    "match_phrase": {
      "address": "huibei,wuhan"
    }
  },
  "sort": [    //指定排序
    {
      "age": {      //对字段age进行排序
        "order": "desc"
      },
      "address": {     //address排序
        "order": "asc"
      }
    }
  ]
}

range

日期查询

  • 可以查询日期的范围,如下:
代码语言:javascript
复制
GET /lib/user/_search
{
  "query": {
  "range": {
    "date": {
      "gt": "2010-11-11",    //大于
      "lt": "2012-12-31"    //小于
    }
  }
  }
}


GET /lib/user/_search
{
  "query": {
  "range": {
    "date": {
      "gt":"now"       //查询大于现在时间的文档
    }
  }
  }
}


GET /lib/user/_search
{
  "query": {
  "range": {
    "date": {
      "gt":"now-1h"    //查询距离现在一小时之内的文档,直接使用now减去一小时即可
    }
  }
  }
}



GET /lib/user/_search
{
  "query": {
  "range": {
    "date": {
      "gt": "2010-11-11 00:00:00",    //指定时分秒查询
      "lt": "2012-12-31 00:00:00"
    }
  }
  }
}

数字

代码语言:javascript
复制
GET /lib/user/_search
{
  "query": {
  "range": {
    "price": {
      "gt": 10,    //数值范围查找
      "lt": 20
    }
  }
  }
}

字符串范围

  • range 查询同样可以处理字符串字段, 字符串范围可采用 字典顺序(lexicographically) 或字母顺序(alphabetically)。例如,下面这些字符串是采用字典序(lexicographically)排序的:
    • 5, 50, 6, B, C, a, ab, abb, abc, b
    • 在倒排索引中的词项就是采取字典顺序(lexicographically)排列的,这也是字符串范围可以使用这个顺序来确定的原因。
代码语言:javascript
复制
"range" : {
    "title" : {
        "gte" : "a",
        "lt" :  "b"
    }
}

wildcard查询

  • 允许使用通配符*和?进行查询
  • *: 代表一个或者多个字符
  • ?:代表任意一个字符
代码语言:javascript
复制
GET team/user/_search
{
  "query": {
    "wildcard": {
      "name":"chen*"   
    }
  }
}


GET team/user/_search
{
  "query": {
    "wildcard": {
      "name":"chen?iabing"
    }
  }
}

模糊查询 fuzzy

  • 假设我们需要查询chenjiabing这个名字,那么使用模糊查询的话,如果其中有个字符写错了,也是能够查询到的
代码语言:javascript
复制
GET team/user/_search
{
  "query": {
    "fuzzy": {
      "name":"chejiabing"
    }
  }
}

高亮查询

代码语言:javascript
复制
GET team/user/_search
{
  "query": {
    "fuzzy": {
      "name":"chejiabing"
    }
  },
  "highlight": {
    "pre_tags": ["<span style='color:red'>"],   //指定包裹的标签前半部分,默认的是<em>
    "post_tags": ["</span>"],                    //指定后半部分
    "fields": {
      "name": {}                               //name字段高量
    }
  }
}

null值的查询

  • exists这个语句用来查询存在值的信息,如果和must结合表示查询不为null的数据,如果must_not集合表示查询为null的数据,如下:
代码语言:javascript
复制
//查询password=null的数据
GET ea/user/_search
{
  "query": {
    "bool": {
      "must_not":{
        "exists":{
          "field":"password"
        }
      }
    }
  }
}


//查询password!=null的数据
GET ea/user/_search
{
  "query": {
    "bool": {
      "must":{
        "exists":{
          "field":"password"
        }
      }
    }
  }
}

filter查询

  • 缓存,不返回相关性,速度比query快

简单的过滤查询

  • 使用post_filter
代码语言:javascript
复制
GET /lib/user/_search
{
  "post_filter": {
    "term": {
      "age":22
    }
  }
}

bool过滤查询

  • 语法如下:
    • must :所有的语句都 必须(must) 匹配,与 AND 等价。
    • must_not :所有的语句都 不能(must not) 匹配,与 NOT 等价。
    • should:至少有一个语句要匹配,与 OR 等价。
代码语言:javascript
复制
{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
   }
}
  • 其中的每一个部分都是可选的
实例
  • must中的内容查询是并列的,相当于sql中的and,所有的条件都满足才可以
代码语言:javascript
复制
GET /lib/user/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {"age":22}},
        {"match":{"address": "湖北"}}
      ]
    }
  }
}


GET /lib/user/_search
{
  "post_filter": {
    "bool": {
       "should": [
        {"term":{"name":"郑元梅"}},
        {"term":{"age":33}}
      ],
      "must_not": [
        {"term":{"age":22}}
      ]
     
    }
  }
}

嵌套bool过滤查询

  • 我们需要执行sql语句如下:
代码语言:javascript
复制
select * from user where name="郑元梅" or age=33 or(age=22 and price=33);
代码语言:javascript
复制
GET /lib/user/_search
{
  "query": {
    "bool": {
       "should": [
        {"term":{"name":"郑元梅"}},
        {"term":{"age":33}},
        {
          "bool": {
            "must": [
              {"term":{"age":22},
              	{"term":{"price":33}}
              }
            ]
          }
        }
      ]
     
    }
  }
}

范围过滤

代码语言:javascript
复制
GET /lib/user/_search
{
  "post_filter": {
    "range": {
      "age": {
        "gte": 20,
        "lte": 21
      }
    }
  }
}

非空的过滤查询

  • select * from user where address is not null
代码语言:javascript
复制

GET /lib/user/_search
{
  "query": {
    "bool": {
      "filter": {
        "exists": {
          "field": "address"
        }
      }
    }
  }
}

聚合查询

  • 在sql中有许多的聚合函数,那么在Elasticsearch中页存在这些聚合函数,比如sum,avg,count等等
代码语言:javascript
复制
GET /lib/user/_search
{
  "size": 0,     //在使用聚合的时候,默认还会返回全部的文档结果,如果不需要,可以使用size限制
  "aggs": {
    "sum_age": {           //sum_age  指定返回字段的名称
      "sum": {            //sum是指定的聚合函数的名称
        "field": "age"    //这里指定聚合的字段
      }
    }
  }
}

GET /lib/user/_search
{
  "size": 0,
  "aggs": {
    "avg_age": {
      "avg": {
        "field": "age"
      }
    }
  }
}


GET /lib/user/_search
{
  "size": 0,
  "aggs": {
    "max_age": {
      "max": {
        "field": "age"
      }
    }
  }
}


GET /lib/user/_search
{
  "size": 0,
  "aggs": {
    "min_age": {
      "min": {
        "field": "age"
      }
    }
  }
}

GET /lib/user/_search
{
  "size": 0,
  "aggs": {
    "cardinality_age": {       
      "cardinality": {        //查询某个字段的基数,就是对应的字段有多少个不同的值
        "field": "age"
      }
    }
  }
}
  • 分组(group),使用的是terms
代码语言:javascript
复制
GET /lib/user/_search
{
  "size": 0,
  "aggs": {
    "age_group": {
      "terms": {
        "field": "date"    //按照日期进行分组
      }
    }
  }
}


//结果如下:

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 6,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "age_group": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": 1352635200000,
          "key_as_string": "2012-11-11 12:00:00",
          "doc_count": 5     //分组的数量	
        },
        {
          "key": 1352592000000,
          "key_as_string": "2012-11-11 00:00:00",
          "doc_count": 1
        }
      ]
    }
  }
}
  • 对年龄是22岁的用户按照date进行分组,如下:
代码语言:javascript
复制
GET /lib/user/_search
{
  "size": 0,
  "query": {
    "term": {
      "age": "22"
    }
  }, 
  "aggs": {
    "age_group": {
      "terms": {
        "field": "date"
      }
    }
  }
}
  • 对年龄是22岁的用户按照date进行分组,并且计算每组的平均年龄
代码语言:javascript
复制
select *,avg(age) from user group by date;
代码语言:javascript
复制
GET /lib/user/_search
{
  "query": {
    "term": {
      "age": "22"
    }
  }, 
  "aggs": {
    "age_group": {
      "terms": {
        "field": "date"
      },
      "aggs": {      //直接在分组的聚合中,再次使用聚合求age的均值
        "age_avg": {
          "avg": {
            "field": "age"
          }
        }
      }
    }
  }
}
  • 对年龄是22岁的用户按照date进行分组,并且计算每组的平均年龄,最后按照平均年龄进行排序
代码语言:javascript
复制
GET /lib/user/_search
{
  "query": {
    "term": {
      "age": "22"
    }
  }, 
  "aggs": {
    "age_group": {
      "terms": {
        "field": "date",
        "order": {
          "age_avg": "asc"    //按照聚合查询的平均年龄进行升序排序
        }
      },
      "aggs": {
        "age_avg": {
          "avg": {
            "field": "age"
          }
        }
      }
    }
  }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 请求体查询
    • 简单查询 【不推荐】
      • 空查询
        • 精确值查找
          • term查询
          • terms
        • 指定文档数量 (from ,size)
          • 返回指定的字段 _source
            • 返回版本号
              • match查询
                • match_all
                  • match_phrase
                    • 排序
                      • range
                        • 日期查询
                        • 数字
                        • 字符串范围
                      • wildcard查询
                        • 模糊查询 fuzzy
                          • 高亮查询
                            • null值的查询
                              • filter查询
                                • 简单的过滤查询
                                • bool过滤查询
                                • 嵌套bool过滤查询
                                • 范围过滤
                                • 非空的过滤查询
                              • 聚合查询
                              相关产品与服务
                              Elasticsearch Service
                              腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档