7-DSL语言高级查询

发布时间 2023-09-23 12:21:12作者: 爱杨帅

概述

关于 DSL

  • DSL(Domain Specific Language)
  • 领域专用语言
  • Elasticsearch 提供了基于 JSON 的 DSL 来定义查询

组成

  • 叶子查询子句:在特定域中寻找特定的值。
  • 复合查询子句:复合查询子句包装其他叶子查询或复合查询,并用于以逻辑方式组合多个查询。

基本语法

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

查询类型

  • match_all
  • match
  • term
  • range
  • ...

DSL 查询

数据准备, 定义索引库:

image-20220112164750218

PUT /my_goods_001
{
  "settings": {},
  "mappings": {
    "properties": {
      "titile":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "img":{
        "type": "keyword"
      },
      "price":{
        "type": "float"
      }
    }
  }
}

添加数据:

POST /my_goods_001/_doc/
{
  "title":"小米12 Pro 5G新品手机",
  "img":"jd/68fefdd1ffa9b2c6.jpg",
  "price":4699
}
POST /my_goods_001/_doc/
{
  "title":"小米电视EA55 2022款",
  "img":"jd/a7b378609674c149.jpg",
  "price":1899
}
POST /my_goods_001/_doc/
{
  "title":"华为Mate40Pro",
  "img":"jd/fb9481c4ca07a2e3.jpg",
  "price":6099
}

image-20220112170155642

查询所有(match_all query)

无查询条件是查询所有,默认是查询所有的,写法如下:

POST /索引库/_search
{
  "query": {
    "match_all": {}
  }
}

image-20220112171530101

POST /my_goods_001/_search
{
  "query": {
    "match_all": {
      
    }
  }
}

返回结果含义:

  • took:查询花费时间,单位是毫秒
  • time_out:是否超时
  • shards:分片信息
  • hits:搜索结果总览对象
    • total:搜索到的总条数
    • max_score:所有结果中文档得分的最高分
    • hits:搜索结果的文档对象数组
      • _index:索引库
      • _type:文档类型
      • _id:文档 id
      • _score:文档得分
      • _source:文档的源数据

全文搜索

match 匹配搜索

对一个字段进行匹配查询,match 类型查询,match 类型查询,会把查询条件进行分词,or 关系,多个词条之间是 or 的关系:

POST /my_goods_001/_search
{
  "query": {
    "match": {
      "title": "小米电视EA55"
    }
  }
}

image-20220112230542524

and 关系:

POST /my_goods_001/_search
{
  "query": {
    "match": {
      "title": {
        "query": "小米电视EA55",
        "operator": "and"
      }
    }
  }
}

image-20220112230646215

短语搜索

对一个字段进行短语查询, 短语匹配:

POST /my_goods_001/_search
{
  "query": {
    "match_phrase": {
      "title": "小米电视"
    }
  }
}

image-20220112230809312

移动因子匹配,关于这个移动因子大概意思就是说假如你现在要搜索一个 小米EA55 如果你的移动因子为 2 那么小米后面两个内容可以是其它的内容然后在拼接EA55来进行查询效果如下:

POST /my_goods_001/_search
{
  "query": {
    "match_phrase": {
      "title": {
        "query": "小米EA55",
        "slop": 2
      }
    }
  }
}

image-20220112231510621

全文搜索可以理解为 MySQL 当中的模糊搜索。

query_string 查询

无需指定某字段而对文档全文进行匹配查询的一个高级查询。

不指定字段

POST /my_goods_001/_search
{
  "query": {
    "query_string": {
      "query": "手机"
    }
  }
}

image-20220112231811340

全字段搜索。

指定字段

POST /my_goods_001/_search
{
  "query": {
    "query_string": {
      "query": 1899,
      "default_field": "price"
    }
  }
}

image-20220112231850228

逻辑查询

POST /my_goods_001/_search
{
  "query": {
    "query_string": {
      "query": "小米 AND 手机",
      "default_field": "title"
    }
  }
}

image-20220112231936549

模糊查询

POST /my_goods_001/_search
{
  "query": {
    "query_string": {
      "query": "小米~1",
      "default_field": "title"
    }
  }
}

image-20220112232023837

这个模糊搜索主要就是对数据进行修正,如上我编写的为 小米~1 ~1 它内部会自动的进行转换修正,可能会修正为如上所查询出来的电视,或者12啥的。

多字段查询

POST /my_goods_001/_search
{
  "query": {
    "query_string": {
      "query": "1899",
      "fields": ["title", "price"]
    }
  }
}

image-20220112232113844

多字段搜索 multi_match

POST /my_goods_001/_search
{
  "query": {
    "multi_match": {
      "query": "1899",
      "fields": ["title", "price"]
    }
  }
}

image-20220113084852752

当然搜索的字段可以是进行模糊匹配字段用 * 来表示如下:

POST /my_goods_001/_search
{
  "query": {
    "multi_match": {
      "query": "1899",
      "fields": ["title", "pr*"]
    }
  }
}

image-20220113084927962

词条精确搜索

词条级搜索(term-level queries) 根据结构化数据中的精确值查找文档,term-level queries 不分析搜索词,演示示例数据准备,创建映射:

PUT /my_goods_002
{
  "settings": {},
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "price": {
        "type": "float"
      },
      "description": {
        "type": "text",
        "analyzer": "ik_max_word"
      },
      
      "create_date": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

image-20220114220652326

添加数据:

PUT /my_goods_002/_doc/1
{
  "name": "Spring实战",
  "description": "全球有超过100 000名开发者使用本书来学习Spring 畅销经典Spring技术图书,针对Spring 5全面升级 Spring框架能够让Java开发人员的工作更加轻松。Spring 5的新特性通过微服务、反应式开发进一步提升了生产效率。",
  "price":49.50,
  "create_date":"2022-01-10 11:12:35"
}

PUT /my_goods_002/_doc/2
{
  "name": "MySQL",
  "description": "SQL必知必会作者力作,深入浅出MySQL高性能讲解技术内幕,紧贴实战需要,适用于广大软件开发和数据库管理人员学习参考",
  "price":24.50,
  "create_date":"2021-12-10 18:11:35"
}

PUT /my_goods_002/_doc/3
{
  "name": "Elasticsearch",
  "description": "Elasticsearch 是一个开源的全文搜索引擎,很多用户对于大规模集群应用时遇到的各种问题难以分析处理,或者知其然而不知其所以然。本书分析 Elasticsearch 中重要模块及其实现原理和机制",
  "price":44.50,
  "create_date":"2021-12-11 14:18:31"
}
PUT /my_goods_002/_doc/4
{
  "name": "Oracle",
  "description": "字典式写作手法:不讲具体语法,没有简单知识堆砌,直接以案例形式讲技巧与案例 大量优化实战方法:将主要SQL优化点一一剖析,分享大量SQL优化的实际工作经验 50余改写调优案例:覆盖大多数DBA日常工作场景",
  "price":44.90,
  "create_date":"2021-11-10 11:12:35"
}

image-20220114220733058

词条搜索

term

查询用于查询指定字段包含某个词项的文档:

POST /my_goods_002/_search
{
  "query": {
    "term": {
      "name": {
        "value": "spring"
      }
    }
  }
}

image-20220114220941839

terms

查询用于查询指定字段包含某些词项的文档:

POST /my_goods_002/_search
{
  "query": {
    "terms": {
      "name": [
        "spring",
        "mysql"
      ]
    }
  }
}

image-20220114221056839

range query

查询指定字段范围的值,范围包括:

  • gt:大于
  • gte:大于等于
  • lt:小于
  • lte:小于等于
  • boost:查询权重

查询指定范围的数据:

POST /my_goods_002/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 10,
        "lte": 50,
        "boost": 1.0
      }
    }
  }
}

image-20220114222315807

查询指定当前日期范围的数据:

POST /my_goods_002/_search
{
  "query": {
    "range": {
      "create_date": {
        "gte": "now-30d/d",
        "lte": "now/d"
      }
    }
  }
}

image-20220114222440759

查询指定特定日期范围的数据:

POST /my_goods_002/_search
{
  "query": {
    "range": {
      "create_date": {
        "gte": "10/12/2021",
        "lte": "2022",
        "format": "dd/MM/yyyy||yyyy"
      }
    }
  }
}

image-20220114222605488

exists query

查询指定字段值不为空的文档:

POST /my_goods_002/_search
{
  "query": {
    "exists": {
      "field": "name"
    }
  }
}

image-20220115092406706

prefix query

词项前缀搜索:

POST /my_goods_002/_search
{
  "query": {
    "prefix": {
      "name": {
        "value": "sp"
      }
    }
  }
}

image-20220115092513896

wildcard query

通配符搜索:

POST /my_goods_002/_search
{
  "query": {
    "wildcard": {
      "name": {
        "value": "sp*g"
      }
    }
  }
}

image-20220115092623315

可以在通配符搜索的情况下还可以指定权重比例值:

POST /my_goods_002/_search
{
  "query": {
    "wildcard": {
      "name": {
        "value": "sp*",
        "boost": 2
      }
    }
  }
}

image-20220115092723073

regexp query

regexp 允许使用正则表达式进行 term 查询,这种方式查询还需谨慎,万一没写好就会造成全查询导致性能下降:

POST /my_goods_002/_search
{
  "query": {
    "regexp": {
      "name": "s.*"
    }
  }
}

fuzzy query

模糊搜索:

POST /my_goods_002/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "sp"
      }
    }
  }
}

没有指定 fuzziness, 查询的内容就是 sp,可以指定 fuzziness 的模糊值:

POST /my_goods_002/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "sg",
        "fuzziness": 2
      }
    }
  }
}

image-20220115095200888

ids

POST /my_goods_002/_search
{
  "query": {
    "ids": {
      "type": "_doc",
      "values": ["1", "3"]
    }
  }
}

image-20220115095258832

复合搜索

constant_score query

用来包装另一个查询,将查询匹配的文档的评分设为一个常值,词条查询时得到文档的分数不一样:

POST /my_goods_002/_search
{
  "query": {
    "term": {
      "description": {
        "value": "开发"
      }
    }
  }
}

image-20220115102031017

使用 constant_score query 将查询匹配的文档的评分设为一个常值:

POST /my_goods_002/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "description": "开发"
        }
      },
      "boost": 1.0
    }
  }
}

image-20220115161234427

bool query

组合多个关键字查询子句进行 bool 类型过滤,可有关键字:

  • must:必须满足
  • filter:必须满足, 执行的是 filter 上下文, 不影响评分
  • should:或者关系
  • must_not:必须不满足
  • minimum_should_match:最小匹配精度,必须指定 should, 0 可以不出现 should,1 必须出现 should
GET /my_goods_002/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "description": "开发"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "name": "spring"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gte": 20,
              "lte": 40
            }
          }
        }
      ],
      "minimum_should_match": 0,
      "boost": 1
    }
  }
}

image-20220115162508542

GET /my_goods_002/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "description": "开发"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "name": "spring"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gte": 20,
              "lte": 40
            }
          }
        }
      ],
      "minimum_should_match": 1,
      "boost": 1
    }
  }
}

image-20220115162526342

排序

相关性评分排序

默认是按照相关性评分进行排序,最相关的文档排在最前:

GET /my_goods_002/_search
{
  "query": {
    "match": {
      "description": "开发"
    }
  },
  "sort": [
    {
      "_score": {
        "order": "asc"
      }
    }
  ]
}

image-20220115162732710

字段值排序

GET /my_goods_002/_search
{
  "query": {
    "match": {
      "description": "开发"
    }
  },
  "sort": [
    {
      "price": {
        "order": "asc"
      }
    }
  ]
}

image-20220115162814566

多级排序

GET /my_goods_002/_search
{
  "query": {
    "match": {
      "description": "开发"
    }
  },
  "sort": [
    {
      "price": {
        "order": "asc"
      },
      "_score": {
        "order": "asc"
      }
    }
  ]
}

image-20220115162903903

分页

GET /my_goods_002/_search
{
  "query": {
    "match": {
      "description": "开发"
    }
  },
  "sort": [
    {
      "price": {
        "order": "asc"
      },
      "_score": {
        "order": "asc"
      }
    }
  ],
  "from": 0,
  "size": 1
}

image-20220115162949486

高亮

highlight 属性:

  • pre_tags:前置标签
  • post_tags:后置标签
  • fields:需要高亮的字段
GET /my_goods_002/_search
{
  "query": {
    "match": {
      "description": "开发"
    }
  },
  "sort": [
    {
      "price": {
        "order": "asc"
      },
      "_score": {
        "order": "asc"
      }
    }
  ],
  "from": 0,
  "size": 1,
  "highlight": {
    "pre_tags": "<font color='red'>",
    "post_tags": "</font>",
    "fields": [
      {
        "description": {}
      }
    ]
  }
}

image-20220115192543875

Filter DSL

  • ElasticSearch 中的所有的查询都会触发相关度 得分 的计算。
  • 对于那些我们不需要相关度得分的场景下,Elasticsearch 以过滤器的形式提供了另一种查询功能。
  • 执行速度快, 过滤器不会计算相关度的得分,所以它们在计算上更快一些, 也不会对结果进行排序, 过滤器可以被缓存到内存中,这使得在重复的搜索查询上,其要比相应的查询快出许多。
GET /my_goods_002/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "description": "开发"
          }
        }
      ]
    }
  }
}

image-20220305133906051

验证语法与分析

  • _validate:对请求的查询语法进行验证

正确示例:

GET /my_goods_002/_validate/query
{
  "query": {
    "term": {
      "name": {
        "value": "spring"
      }
    }
  }
}

image-20220305134142598

错误示例:

GET /my_goods_002/_validate/query
{
  "query": {
    "term1": {
      "name": {
        "value": "spring"
      }
    }
  }
}

image-20220305134156836

  • explain,explain 是一个参数,作用可用于对验证的结果进行分析
GET /my_goods_002/_validate/query?explain
{
  "query": {
    "term1": {
      "name": {
        "value": "spring"
      }
    }
  }
}

image-20220305134224242

批量操作

批量查询

查询指定 id 的数据信息:

GET /my_goods_002/_mget
{
  "docs": [
    {
      "_id": 1
    },
    {
      "_id": 4
    }
  ]
}

批量创建文档 create

如下代码的含义为,创建两条数据,create 与 id 这两行才代表是一条数据:

POST _bulk
{"create":{"_index":"my_goods_002","_type":"_doc","_id":"6"}}
{"id":"6","name":"新增6","description":"new description","price":"55.5","create_date":"2021-12-11 14:18:31"}
{"create":{"_index":"my_goods_002","_type":"_doc","_id":"7"}}
{"id":"7","name":"新增7","description":"new description","price":"55.5","create_date":"2021-12-11 14:18:31"}

批量删除

可以先创建测试数据,然后在执行如下删除:

POST _bulk
{"delete":{"_index":"my_goods_002","_type":"_doc","_id":"5"}}
{"delete":{"_index":"my_goods_002","_type":"_doc","_id":"6"}}
{"delete":{"_index":"my_goods_002","_type":"_doc","_id":"7"}}

批量修改

修改完毕之后你可以在查询一下你修改的数据是否成功即可:

POST _bulk
{"update":{"_index":"my_goods_002","_type":"_doc","_id":"6"}}
{"doc":{"name":"update新增"}}

普通创建或全量替换 index

如果对应的数据存在就是修改操作,如果不存在相应的数据就是创建操作:

存在的情况:

POST _bulk
{"index":{"_index":"my_goods_002","_type":"_doc","_id":"6"}}
{"id":"6","name":"全量修改或者新增6","description":"new description","price":"55.5","create_date":"2021-12-11 14:18:31"}
{"index":{"_index":"my_goods_002","_type":"_doc","_id":"7"}}
{"id":"7","name":"全量修改或者新增7","description":"new description","price":"55.5","create_date":"2021-12-11 14:18:31"}

image-20220305140042822

不存在的情况:

image-20220305140109801

聚合分析

完成对一个查询的数据集中数据的聚合计算。

指标聚合 metric

对一个数据集求最大、最小、和、平均值等指标的聚合。

关键字

  • max
  • min
  • sum
  • avg
POST /my_goods_002/_search
{
  "size": 0,
  "aggs": {
    "max_price": {
      "max": {
        "field": "price"
      }
    }
  }
}

image-20220305141937587

文档统计 count

POST /my_goods_002/_count
{
  "query": {
    "range": {
      "price": {
        "gte": 10,
        "lte": 50
      }
    }
  }
}

image-20220305142101049

value_count

统计某字段有值的文档数, 就是说一个索引库当中某个文档里面字段不为空的数据的统计:

POST /my_goods_002/_search
{
  "size": 10,
  "aggs": {
    "price_count": {
      "value_count": {
        "field": "create_date"
      }
    }
  }
}

cardinality

值去重计数,如下代码的含义为,去 _id 进行去重然后进行总结去重之后的总量值:

POST /my_goods_002/_search
{
  "aggs": {
    "_id_count": {
      "cardinality": {
        "field": "_id"
      }
    }
  }
}

stats

统计 count、max、min、avg、sum、5个值的结果:

POST /my_goods_002/_search?size=0
{
  "aggs": {
    "price_stats": {
      "stats": {
        "field": "price"
      }
    }
  }
}

image-20220305142612231

桶聚合 bucketing

也就是再次对查询出的数据进行分组 group by,再在组上进行指标聚合。

image-20220305143649266

如上的这一个示例的含义为,首先是对价格字段进行一次分组操作,不同价格范围的会被分配到不同组当中,然后下面的聚合操作就是对每组当中的内容进行求和操作。

POST /my_goods_002/_search?size=0
{
  "aggs": {
    "group_price": {
      "range": {
        "field": "price",
        "ranges": [
          {
            "from": 10,
            "to": 20
          },
          {
            "from": 20,
            "to": 30
          },
          {
            "from": 30,
            "to": 40
          },
          {
            "from": 40,
            "to": 50
          }
        ]
      },
      "aggs": {
        "sum_price": {
          "sum": {
            "field": "price"
          }
        },
        "having": {
          "bucket_selector": {
            "buckets_path": {
              "sum_price": "sum_price"
            },
            "script": "params.sum_price >= 30"
          }
        }
      }
    }
  }
}

看了第一个示例在来看这个示例的时候是否发现在聚合当中博主又多添加了一点内容呢,对的,就是 having 那一串,having 是自定义的博主为了让你们更加的容易理解就刻意去定义为 having 的,其实叫啥都可以,然后 bucket_selector 当中的 buckets_path 当中的内容就是 aggs 后面的 sum_price 属性名即可,script 当中编写的内容就是说去获取 buckets_path 当中的内容,博主获取的就是 buckets_path 当中的 sum_price 每组当中的值,然后筛选值大于等于 30 的数据出来:

image-20220305144255308