一、高级查询Query DSL简介

1、Query DSL(简介

Elasticsearch中提供了一种强大的检索数据方式,这种检索方式称之为Query DSL(Domain Specified Language) 。

Query DSL是利用 Rest API传递 JSON格式的请求体(RequestBody)数据与 ES进行交互,这种方式的丰富查询语法让 ES检索变得更强大,更简洁。

基本语法:

GET /es_db/_doc/_search {json请求体数据} 
#可以简化为下面写法 
GET /es_db/_search {json请求体数据} 

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl.html

2、测试数据

示例数据:

#创建索引,并指定ik分词器 
PUT /db_idx4
{
    "settings":{
        "index":{
            "analysis.analyzer.default.type":"ik_max_word"
        }
    }
}
# 批量创建文档
POST _bulk
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":1}}
{"id":1,"name":"赵子龙","sex":1,"age":18, "address":"三国演义常山赵子龙", "desc":"刘备大将之一"} 
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":2}}
{"id":2,"name":"赵云","sex":1,"age":19, "address":"王者打野刺客赵云", "desc":"王者刺客"} 
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":3}}
{"id":3,"name":"关云长","sex":1,"age":23, "address":"三国演义关云长", "desc":"桃园结义刘备二弟"} 
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":4}}
{"id":4,"name":"关羽","sex":1,"age":23, "address":"王者边路", "desc":"可辅可边"} 
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":5}}
{"id":5,"name":"张益德","sex":1,"age":22, "address":"三国演义张益德", "desc":"桃园结义刘备三弟"} 
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":6}}
{"id":6,"name":"张飞","sex":1,"age":22, "address":"王者辅助", "desc":"王者辅助"} 
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":7}}
{"id":7,"name":"张玄德","sex":1,"age":25, "address":"三国演义张玄德", "desc":"桃园结义刘皇叔"} 
{"index":{"_index":"db_idx4", "_type":"_doc", "_id":8}}
{"id":8,"name":"小乔","sex":0,"age":18, "address":"三国演义小乔", "desc":"周瑜之妻"}

二、查询操作

1、查询所有match_all

使用 match_all,默认只会返回 10条数据。

原因:_search查询默认采用的是分页查询,每页记录数 size的默认值为 10。如果想显示更多数据,指定 size 。

#使用 match_all,默认只会返回 10条数据。
GET /db_idx4/_search 
#等同于 
GET /db_idx4/_search 
{
    "query":{
        "match_all":{

        }
    }
}

1.1 指定条数size

size 关键字:指定查询结果中返回指定条数。 默认返回值10条。

# 指定 size 
GET /db_idx4/_search 
{
    "query":{
        "match_all":{

        }
    },
    "from":1,
    "size":3
}

1.2 分页查询form

from 关键字:用来指定起始返回位置,和size关键字连用可实现分页效果

GET /db_idx4/_search 
{
    "query":{
        "match_all":{

        }
    },
    "from":2,
    "size":200
}

如果 size = 30000,,就会出现异常。

在这里插入图片描述

  • 查询结果的窗口太大,from + size的结果必须小于或等于10000。
  • 查询结果的窗口的限制可以通过参数 index.max_result_window进行设置。
  • 也可以采用 scroll api更高效的请求大量数据集。
#修改现有某个的索引
PUT /db_idx4/_settings 
{
    "index.max_result_window":"20000"
}

2、深分页查询Scroll

改动 index.max_result_window参数值的大小,只能解决一时的问题,当索引的数据量持续增长时,在查询全量数据时还是会出现问题。而且会增加 ES服务器内存大结果集消耗完的风险。

最佳实践还是根据异常提示中的采用 scroll api更高效的请求大量数据集。

GET /db_idx4/_search?scroll=1m
{
    "query":{
        "match_all":{

        }
    },
    "size":2
}

在这里插入图片描述

查询结果: 除了返回前2条记录,还返回了一个游标ID值_scroll_id

2.1 采用游标id查询:

# scroll_id 的值就是上一个请求中返回的 _scroll_id 的值 
GET /_search/scroll 
{
    "scroll":"1m",
    "scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFmNpTWtscHBSUnVxYmM0ZEtrc1hGMGcAAAAAAAA1ABZlYko0RmdtUlNUT0ItcUo2TDNMbjdn"
}

多次根据 scroll_id游标查询,直到没有数据返回则结束查询。采用游标查询索引全量数据, 更安全高效,限制了单次对内存的消耗。

3、指定字段排序sort

注意:会让得分失效。

GET /db_idx4/_search
{
    "query":{
        "match_all":{

        }
    },
    "sort":[
        {
            "age":"desc"
        }
    ]
}

4、_source返回指定字段

_source 关键字:是一个数组,在数组中用来指定展示那些字段。

GET /db_idx4/_search
{
  "query": {
    "match_all": {}
  },
  "_source": ["name","address"]
}

5、match 查找

match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找

match支持下面几个参数:

  • query:指定匹配的值
  • operator:匹配条件类型
  • and:条件分词后都要匹配
  • or:条件分词后有一个匹配即可(默认)
  • minmum_should_match :最低匹配度,即条件在倒排索引中最低的匹配度
#模糊匹配 match 分词后or的效果 
GET /db_idx4/_search
{
  "query": {
    "match": {
      "address": "王者打野"
    }
  }
}

#分词后 and的效果 
GET /db_idx4/_search
{
  "query": {
    "match": {
      "address": {
        "query": "王者打野",
        "operator": "and"
      }
    }
  }
}

当 operator参数设置为 or时,minnum_should_match参数用来控制匹配的分词的最少数量。

#最少匹配打野,刺客两个词 
GET /db_idx4/_search
{
  "query": {
    "match": {
      "address": {
        "query": "刺客打野",
        "operator": "or",
        "minimum_should_match": 2
      }
    }
  }
}

6、多字段查询multi_match

multi_match 关键字:可以根据字段类型,决定是否使用分词查询,得分最高的在前面。

GET /db_idx4/_search
{
  "query":{
    "multi_match": {
      "query": "王者打野",
      "fields": ["address", "desc"]
    }
  }
}

注意:字段类型分词,将查询条件分词之后进行查询,如果该字段不分词就会将查询条件作为整体进行查询。

7、query_string 查询

允许我们在单个查询字符串中指定 AND | OR | NOT条件,同时也和 multi_match query 一样,支持多字段搜索。和match类似,但是 match需要指定字段名,query_string是在所有字段中搜索,范围更广泛。

注意:查询字段分词就将查询条件分词查询,查询字段不分词将查询条件不分词查询。

#未指定字段查询 
GET /db_idx4/_search
{
  "query":{
    "query_string": {
      "query": "赵云 OR 赵子龙"
    }
  }
}

#指定单个字段查询 
GET /db_idx4/_search
{
  "query":{
    "query_string": {
      "default_field": "address", 
      "query": "赵云 OR 赵子龙"
    }
  }
}

#指定多个字段查询 
GET /db_idx4/_search
{
  "query":{
    "query_string": {
      "fields": ["address","name"], 
      "query": "赵云 OR 赵子龙 OR 张飞"
    }
  }
}

8、simple_query_string 查询语法

类似Query String,但是会忽略错误的语法,同时只支持部分查询语法,不支持AND OR NOT,会当作字符串处理。

支持部分逻辑:

  • “+” 替代AND
  • “|” 替代OR
  • “-” 替代NOT
#simple_query_string 默认的operator是OR 
GET /db_idx4/_search 
{
  "query":{
    "simple_query_string": {
      "query": "王者打野",
      "fields": ["address","desc"], 
      "default_operator": "OR"
    }
  }
}

GET /db_idx4/_search 
{
  "query":{
    "simple_query_string": {
      "query": "王者+打野",
      "fields": ["address","desc"]
    }
  }
}

9、关键词查询Term

Term用来使用关键词查询(精确匹配),还可以用来查询没有被进行分词的数据类型。

  • term是表达语意的最小单位,搜索和利用统计语言模型进行自然语言处理都需要处理Term。
  • match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找,而 term会直接对关键词进行查找。

一般模糊查找的时候,多用 match,而精确查找时可以使用 term。

在 ES中默认使用分词器为标准分词器(Standard Analyzer)标准分词器对于英文单词分词,对于中文单字分词。

在 ES的 Mapping Type 中 keyword,date,integer,long,double,boolean or ip 这些类型不分词,只有 text类型分词。

GET /db_idx4/_search
{
  "query": {
    "term": {
          "address.keyword": "三国演义小乔"
        }
  }
}

可以通过 Constant Score 将查询转换成一个 Filtering,避免算分,并利用缓存,提高性能。

GET /db_idx4/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "address.keyword": "三国演义小乔"
        }
      }
    }
  }
}

对bool,日期,数字,结构化的文本可以利用 term做精确匹配。

GET /db_idx4/_search
{
  "query": {
    "term": {
      "age": {
        "value": 18
      }
    }
  }
}

10、范围查询range

range:范围关键字:

  • gte 大于等于
  • lte 小于等于
  • gt 大于
  • lt 小于
  • now 当前时间
POST /db_idx4/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 18,
        "lte": 20
      }
    }
  }
} 

11、日期range

DELETE /product 
POST /product/_bulk 
{"index":{"_id":1}} 
{"price":100,"date":"2022‐01‐01","productId":"XHDK‐1293"} 
{"index":{"_id":2}} 
{"price":200,"date":"2022‐02‐01","productId":"KDKE‐5421"} 

GET /product/_mapping 

GET /product/_search
{
  "query": {
    "range": {
      "date": {
        "lte": "now‐2y"
      }
    }
  }
}

12、多id查询ids

ids 关键字 :值为数组类型,用来根据一组id获取多个对应的文档。

GET /db_idx4/_search
{
  "query": {
    "ids": {
      "values": [
        1,
        2
      ]
    }
  }
} 

13、高亮highlight

highlight 关键字:可以让符合条件的文档中的关键词高亮。

highlight相关属性:

  • pre_tags 前缀标签
  • post_tags 后缀标签
  • tags_schema 设置为 styled可以使用内置高亮样式
  • require_field_match 多字段高亮需要设置为false
GET /db_idx4/_search
{
  "query": {
    "term": {
      "address": {
        "value": "王者"
      }
    }
  },
  "highlight": {
    "fields": {
      "*": {}
    }
  }
}

13.1 自定义高亮html标签

可以在highlight中使用 pre_tags和 post_tags。

GET /db_idx4/_search
{
  "query": {
    "term": {
      "address": {
        "value": "王者"
      }
    }
  },
  "highlight": {
    "post_tags": [
      "</span>"
    ],
    "pre_tags": [
      "<span style='color:red'>"
    ],
    "fields": {
      "*": {}
    }
  }
} 

13.2 多字段高亮

GET /db_idx4/_search
{
  "query": {
    "term": {
      "address": {
        "value": "王者"
      }
    }
  },
  "highlight": {
    "pre_tags": [
      "<font color='red'>"
    ],
    "post_tags": [
      "<font/>"
    ],
    "require_field_match": "false",
    "fields": {
      "address": {},
      "desc": {}
    }
  }
} 

更多使用可查看官方文档。

– 求知若饥,虚心若愚。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐