【ES】ElasticSearch 结构化查询和过滤

一、DSL

在 ElasticSearch 中,提供了功能十分丰富、多种表现形式的查询语言—— DSL 查询。

Query DSL 又叫结构化查询,使用 JSON 格式的请求体 与 ElasticSearch 交互,使查询语句更灵活、更精确、更易读且易调试。

使用结构化查询,你需要传递 query 参数:

GET /_search
{
    "query": YOUR_QUERY_HERE
}

主要包含两种类型的查询语句:叶子查询语句复合查询语句

1.1、叶子查询语句

这种查询可以单独使用,针对指定的字段查询指定的值,例如:match, term, range 等。

一个叶子查询语句一般使用这种结构:

{
    QUERY_NAME: {
        ARGUMENT: VALUE,
        ARGUMENT: VALUE,...
    }
}

或指向一个指定的字段:

{
    QUERY_NAME: {
        FIELD_NAME: {
            ARGUMENT: VALUE,
            ARGUMENT: VALUE,...
        }
    }
}

例如,可以使用 match 查询子句用来找寻在 tweet 字段中找寻包含 elasticsearch 的成员:

GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    }
}

1.2、复合查询语句

这种查询可以合并其他的叶子查询或复合查询,从而实现非常复杂的查询逻辑。

例如,bool 子句允许合并其他的合法子句,mustmust_not 或者 should

{
    "bool": {
        "must":     { "match": { "tweet": "elasticsearch" }},
        "must_not": { "match": { "name":  "mary" }},
        "should":   { "match": { "tweet": "full text" }}
    }
}

二、Query DSL 和 Filter DSL

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

查询与过滤语句非常相似,但是它们由于使用目的不同而稍有差异。

2.1、Query DSL

在上下文查询语境中,查询语句会询问文档与查询语句的匹配程度,它会判断文档是否匹配并计算相关性评分(_score)的值。

例如:

  • 查找与 full text search 这个词语最佳匹配的文档
  • 查找包含单词 run,但是也包含runs, running, jogsprint的文档
  • 同时包含着 quick, brownfox— 单词间离得越近,该文档的相关性越高
  • 标识着 lucene, searchjava— 标识词越多,该文档的相关性越高

一条查询语句会计算每个文档与查询语句的相关性,然后给出一个相关性评分 _score,并且按照相关性对匹配到的文档进行排序。

2.2、Filter DSL

在上下文过滤语境中,查询语句主要解决文档是否匹配的问题,而不会在意匹配程度(相关性评分)。

例如:

  • created 的日期范围是否在 20132014 ?
  • status 字段中是否包含单词 “published” ?
  • lat_lon 字段中的地理位置与目标点相距是否不超过10km ?

2.3、比较

相关度:

  • filter —— 只根据搜索条件过滤出符合的文档,将这些文档的评分固定为1,忽略 TF/IDF 信息,不计算相关度分数;
  • query —— 先查询符合搜索条件的文档, 然后计算每个文档对于搜索条件的相关度分数,再根据评分倒序排序。

性能:

  • filter 性能更好,无排序 —— 不计算相关度分数,不用根据相关度分数进行排序,同时 ES 内部还会缓存(cache)比较常用的 filter 的数据 (使用bitset <0或1> 来记录包含与否);
  • query性能较差, 有排序 —— 要计算相关度分数, 要根据相关度分数进行排序, 并且没有cache功能。

原则上来说,使用查询语句做全文本搜索或其他需要进行相关性评分的时候,剩下的全部用过滤语句。

在进行搜索时,常常会在查询语句中,结合查询和过滤来达到查询目的:

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "range": { "date": { "gte": "2014-01-01" }} 
        }
    }
}

三、重要的查询过滤语句

3.1、match

match查询是一个标准查询,不管全文本查询还是精确查询基本上都要用到它。

如果使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析查询字符:

{
    "match": {
        "tweet": "About Search"
    }
}

如果用match下指定了一个确切值,在遇到数字,日期,布尔值或者not_analyzed 的字符串时,它将搜索给定的值:

{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}

提示: 做精确匹配搜索时,最好用过滤语句,因为过滤语句可以缓存数据。

3.2、multi_match

multi_match查询允许做match查询的基础上同时搜索多个字段:

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}

3.3、match_phrase

短语查询,精确匹配。查询a red会匹配包含a red短语的,而不会进行分词查询,也不会查询出包含a 其他词 red这样的文档。

{
    "query": {
        "match_phrase": {
            "ad": "a red"
        }
    }
}

3.4、match_all

使用match_all 可以查询到所有文档,是没有查询条件下的默认语句:

{
    "match_all": {}
}

此查询常用于合并过滤条件。 比如说需要检索所有的邮箱,所有的文档相关性都是相同的,所以得到的_score为1。

3.5、term

term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed的字符串(即不进行分词器分析,文档中必须包含整个搜索的词汇):

{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}

3.6、terms

termsterm 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配,类似于 MySQL 的 in 条件:

{
    "terms": {
        "tag": [ "search", "full_text", "nosql" ]
        }
}

3.7、range

range允许按照指定范围查找一批数据:

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}

范围操作符包含:

  • gt :: 大于
  • gte:: 大于等于
  • lt :: 小于
  • lte:: 小于等于

3.8、exists

用于查找那些指定字段中有值或无值的文档。

指定title字段有值:

{
    "exists":   {
        "field":    "title"
    }
}

指定title字段无值:

{
    "query": {
        "bool": {
            "must_not": {
                "exists": {
                    "field": "group"
                }
            }
        }
    }
}

注:missing 查询无值已经被取消。

3.9、bool

bool 可以用来合并多个条件查询结果的布尔逻辑,它包含一下操作符:

  • must :: 多个查询条件的完全匹配,相当于 and
  • should :: 至少有一个查询条件匹配,相当于 or
  • must_not :: 多个查询条件的相反匹配,相当于 not,忽略相关性评分
  • filter:: 必须匹配,忽略相关性评分
POST /_search
{
    "query": {
        "bool" : {
            "must" : {
              "term" : { "last_name" : "smith" }
            },
            "filter": {
              "term" : { "info.interests" : "musics" }
            },
            "must_not" : {
              "range" : {
                "info.age" : { "gte" : 10, "lte" : 25 }
              }
            },
            "should" : [
              { "term" : { "full_name" : "john" } },
              { "term" : { "full_name" : "smith" } }
            ]
        }
    }
}

提示: 如果bool 查询下没有must子句,那至少应该有一个should子句。但是 如果有must子句,那么没有should子句也可以进行查询。

四、验证查询

查询语句可以变得非常复杂,特别是与不同的分析器和字段映射相结合后,就会有些难度。

validate API 可以验证一条查询语句是否合法。

GET /gb/tweet/_validate/query
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}

请求的返回值说明这条语句是非法的:

{
  "valid" :         false,
  "_shards" : {
    "total" :       1,
    "successful" :  1,
    "failed" :      0
  }
}

想知道语句非法的具体错误信息,需要加上 explain 参数:

GET /gb/tweet/_validate/query?explain 
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}

explain 参数可以提供语句错误的更多详情,很显然,这里把 query 语句的 match 与字段名位置弄反了。

五、参考资料

ES 权威指南

Elasticsearch 简介 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。 elasticSearch 的使用场景 1、在海量数据前提下,对数据进行检索。比如:京东,淘宝等电商项目 课程目标: 1. 了解企业级搜索引擎 2. 安装elasticsearch {linux 系统} 3. 安装kibana并利用kibana对Elasticsearch 索引中的数据进行搜索、查看、交互操作 4. 项目实战{ELK} 课程目录: 01 课程介绍 02 elasticsearch 简介 03 elasticsearch 使用场景 04 安装elasticsearch 之前先安装jdk 05 安装elasticsearch 06 测试elasticsearch是否安装成功  07 安装kibana 08 elasticsearch 基本认识 以及添加索引和删除索引 09 elasticsearch 添加查询数据 10 elasticsearch 修改删除数据 11 elasticsearch 有条件的查询 12 分词子属性fuzzy查询 13 elasticsearch 过滤使用 14 elasticsearch 排序与分页 15 elasticsearch 如何查询指定的字段 16 elasticsearch 高亮显示 17 elasticsearch 聚合 18 elasticsearch mapping 概念 19 elasticsearch 的中文词库 20 elasticsearch 中文词库安装测试 21 elasticsearch 中文词库的使用案例 22 elasticsearch 自定义词库配置 23 安装nginx 配置中文词库 24 测试elasticsearch 自定义中文词库 25 搭建项目父工程 26 搭建项目bean-interface-common 27 搭建search 的service web 项目 28 测试项目是否能与elasticsearch联通 29 创建数据库并搭建首页 30 数据上传功能的实现类完成 31 数据上传控制器完成 32 dubbo 介绍以及安装zookeeper 33 将数据从mysql 上传到elasticsearch 中 34 elasticsearch查询功能分析 35 编写业务需求的dsl 语句 36 编写输入参数返回结果集的实体类 37 实现类编写 38 编写实现类中dsl 语句 39 返回集结果转换 40 结果测试 41 测试通过输入查询条件并将数据显示到页面
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页