zoukankan      html  css  js  c++  java
  • Elastic Search中DSL Query的常见语法

    Query DSL是一种通过request body提交搜索参数的请求方式。就是将请求头参数(?xxx=xxx)转换为请求体参数。
    语法格式:
    GET [/index_name/type_name]/_search
    {
    "query_name" : {
    "argument" : "value" [, ....]
    },
    "query_name" : {
    "field_name" : {
    "argument" : "value" [, ....]
    }
    }
    }
    4.1 测试数据
    PUT /test_index
    {
    "mappings": {
    "test_type" : {
    "properties": {
    "dept_name" : {
    "type" : "keyword"
    },
    "emps.name" : {
    "type" : "text",
    "analyzer": "standard"
    },
    "emps.age" : {
    "type": "long"
    },
    "num_of_emps" : {
    "type": "long"
    },
    "tags" : {
    "type" : "keyword"
    }
    }
    }
    }
    }

    PUT /test_index/test_type/1
    {
    "dept_name" : "Sales Department",
    "emps" : [
    { "name" : "zhangsan", "age" : 20, "join_date" : "2018-07-10" },
    { "name" : "wangwu", "age" : 22, "join_date" : "2018-07-10" }
    ],
    "num_of_emps" : 2,
    "tags" : [ "Sales tag1", "Sales tag2", "Sales tag3" ]
    }

    PUT /test_index/test_type/2
    {
    "dept_name" : "Development Department",
    "emps" : [
    { "name" : "Rod Johnson", "age" : 40, "join_date" : "2016-07-10" },
    { "name" : "James Gosling", "age" : 41, "join_date" : "2017-07-10" },
    { "name" : "Patrick Lencioni", "age" : 42, "join_date" : "2018-01-10" }
    ],
    "num_of_emps" : 3,
    "tags" : [ "Development tags1", "Development tags2", "Development tags3" ]
    }

    4.2 搜索案例
    全查询
    GET /test_index/test_type/_search
    {
    "query" : {
    "match_all" : {}
    }
    }
    单字段匹配
    GET /test_index/test_type/_search
    {
    "query" : {
    "match" : { "emps.name" : "zhangsan" }
    }
    }
    组合条件:
    用java来描述 : ( a > 3 && ( b < 10 || c == 6 ) )
    bool - 用于组合多条件,相当于java中的布尔表达式。相当于最外层的括号,也就是完整的布尔表达式。
    must - 必须符合要求, 相当于java中的逻辑运算符 ==或&&。在must范围内的条件都必须满足。
    must_not - 必须不符合要求, 相当于java中的逻辑运算符 !
    should - 有任意条件符合要求即可,相当于java中的逻辑运算符 ||,在should范围内的条件,只要有任意一个满足即可。
    range - 数学比较条件。计算数学范围的。
    常见的搜索方式在后续案例中演示。
    GET /test_index/test_type/_search
    {
    "query": {
    "bool": {
    "must": [
    {
    "match": {
    "dept_name": "Sales Department"
    }
    }
    ],
    "must_not": [
    {
    "range": {
    "num_of_emps": {
    "gt": 10
    }
    }
    }
    ],
    "should": [
    {
    "match": {
    "emps.name": "wangwu"
    }
    },
    {
    "range": {
    "emps.age": {
    "lte": 10
    }
    }
    }
    ]
    }
    }
    }
    4.2.1 match
    根据某条件搜索document。match会根据field对应的analyzer对搜索条件做分词。并在倒排索引中搜索数据。
    GET /_search
    {
    "query" : {
    "match" : { "dept_name" : "Sales Department" }
    }
    }
    4.2.2 multi match
    使用搜索条件,在多个字段中进行全文检索,搜索document数据。也会将搜索条件使用字段的analyzer做分词。
    GET /_search
    {
    "query" : {
    "multi_match": {
    "query": "rod",
    "fields": ["dept_name", "emps.name"]
    }
    }
    }
    4.2.3 range
    数学比较搜索
    GET /_search
    {
    "query" : {
    "range" : {
    "emps.age" : {
    "gt" : 21, "lte" : 45
    }
    }
    }
    }
    在ES中range也可以实现日期的比较,如:查询40天以内入职的员工。其语法为:
    GET /test_index/_search
    {
    "query": {
    "range": {
    "emps.join_date": {
    "gte": "2018-08-10||-40d"
    }
    }
    }
    }

    4.2.4 term
    词组比较,词组搜索。
    忽略搜索条件分词,使用搜索条件进行精确匹配。进行匹配搜索的字段mapping建议手工创建,且type值为keyword。ES在处理keyword类型的字符串时,不进行分词操作。term搜索可执行。ES中对数字,日期,boolean类型数据也不会做分词操作。
    在ES5.x版本后,为text类型的field默认会创建一个子字段,子字段命名为field_name.keyword,这个字段是不做分词的,默认字段长度最大256个字符。
    GET /_search
    {
    "query" : {
    "term" : {
    "dept_name" : "Sales Department"
    }
    }
    }
    4.2.5 terms
    与term含义相同,就是可以比对多个搜索条件数据
    GET /_search
    {
    "query" : {
    "terms" : {
    "tags" : [ "Sales tag1", "Development tags3" ]
    }
    }
    }
    4.2.6 复合搜索
    在一个请求体中,有多个搜索条件,就是复合搜索。如:搜索数据,条件为部门名称是Sales Department,部门员工数量少于10人,部门员工入职时间晚于2017-01-01,部门员工中一定有人叫zhangsan。上述条件中,部门名称可选,部门员工数量必须满足要求,部门员工入职时间和人名有任意一个条件满足即可。
    在执行复合条件搜索的时候,命令也是有内外顺序的。总体来说就是:"bool" : { "must" : { "action" : {} }, "should" : { "action" : {} }, "must_not" : { "action" : {} }, bool: {}}。 bool命令是可以嵌套的。而"action"代表的就是具体的比对方式,如:match,range等。
    GET /test_index/_search
    {
    "query": {
    "bool": {
    "must": [
    {
    "range": {
    "num_of_emps": {
    "lt": 10
    }
    }
    }
    ],
    "should": [
    {
    "match": {
    "dept_name": "Sales Department"
    }
    },
    {
    "match": {
    "emps.name": "zhangsan"
    }
    },
    {
    "range": {
    "emps.join_date": {
    "gte": "2017-01-01"
    }
    }
    }
    ]
    }
    }
    }
    4.2.7 排序
    在ES的搜索中,默认是使用相关度分数实现排序的。可以通过搜索语法实现定制化排序。
    GET test_index/_search
    {
    "query": {
    "match_all": {}
    },
    "sort": [
    {
    "num_of_emps": {
    "order": "asc"
    }
    },
    {
    "dept_name": {
    "order": "desc"
    }
    }
    ],
    "_source": ["dept_name", "num_of_emps"]
    }
    注意:在ES中,如果使用字符串类型的字段作为排序依据,可能会有问题,尤其是字段类型为text时,ES需要对字段数据做分词,建立倒排索引。如果使用text类型字段做排序,ES给出的排序结果未必友好,毕竟分词后,先使用哪一个单词做排序是不固定的。如:
    PUT /test_sort/sort_type/1
    {
    "content" : "first content",
    "order" : 1
    }
    PUT /test_sort/sort_type/2
    {
    "content" : "second content",
    "order" : 2
    }

    GET /test_sort/sort_type/_search
    {
    "query" : {
    "match" : {
    "content" : "content"
    }
    },
    "sort" : [
    {
    "content" : { "order" : "asc" }
    }
    ]
    }
    此时需要对字段content进行特殊处理,处理如下:为字符串字段增加子字段sf(sort field),这个字段类型为keyword类型(不进行分词),排序时使用这个子字段content.sf作为排序字段即可。在ES5.x版本之后,ES默认为每一个text类型的字段建立一个子字段。子字段类型为keyword,可以实现排序机制。
    DELETE /test_sort

    PUT /test_sort
    {
    "mappings": {
    "sort_type": {
    "properties": {
    "content" : {
    "type": "text",
    "analyzer": "standard",
    "fields": {
    "sf" : {
    "type": "keyword"
    }
    }
    },
    "order" : {
    "type": "long"
    }
    }
    }
    }
    }

    PUT /test_sort/sort_type/1
    {
    "content" : "first content",
    "order" : 1
    }
    PUT /test_sort/sort_type/2
    {
    "content" : "second content",
    "order" : 2
    }

    GET /test_sort/sort_type/_search
    {
    "query" : {
    "match_all" : {}
    },
    "sort" : [
    {
    "content.sf" : { "order" : "desc" }
    }
    ]
    }
    4.2.8 scroll搜索
    如果需要一次性搜索出10万数据,那么执行效率一定不会很高,这个时候可以使用scroll滚动搜索的方式实现搜索。scroll滚动搜索类似分页,是在搜索的时候,先查询一部分,之后再查询下一部分,分批查询总体数据。可以实现一个高效的响应。
    scroll搜索会在第一次搜索的时候保存一个快照,这个快照保存的时长由请求指定,后续的查询会依据这个快照执行再次查询。如果这个过程中,ES中的document发生了变化,是不会影响到原搜索结果的。
    scroll搜索时,需要指定一个排序,可以使用_doc实现排序,这种排序性能更高一些。
    scroll搜索的2次以后的请求,必须在指定的快照保存时长内发起,且每次请求都需要指定这个快照保存时长。
    scroll搜索的返回结果一定会包含一个特殊的结果数据_scroll_id。这个数据就是scroll搜索的快照ID。scroll搜索的2次以后的请求,必须携带上这个ID,否则无法依据ES保存的快照执行后续的搜索。
    测试:
    GET /t_index/_search?scroll=1m
    {
    "query": {
    "match_all": {}
    },
    "sort": [ "_doc" ],
    "size" : 1
    }

    GET /_search/scroll
    {
    "scroll" : "1m",
    "scroll_id" : "根据具体返回结果替换"
    }
    scroll不是分页,不是用来替换分页搜索的技术。一般来说,分页是为用户提供数据的,scroll是为系统内部处理分批提供数据的。如:reindex 重建索引。

  • 相关阅读:
    用ZooKeeper做为注册中心搭建基于Spring Cloud实现服务注册与发现
    spring-cloud-starter-hystrix(断路器)服务不通或者调用失败后的错误处理和回调
    spring-boot-starter-actuator(健康监控)配置和使用
    为什么Java使用System.getenv()获取刚刚设置的环境变量时为空
    Java获取系统环境变量(System Environment Variable)和系统属性(System Properties)以及启动参数的方法
    为什么Linux下的环境变量要用大写而不是小写
    Spring Boot在开发时实现热部署(开发时修改文件保存后自动重启应用)(spring-boot-devtools)
    Ubuntu 16.04添加多张虚拟网卡
    Javascript网址跳转方法
    MySQL出现:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure Last packet sent to the server was 0 ms ago.
  • 原文地址:https://www.cnblogs.com/yucongblog/p/11973581.html
Copyright © 2011-2022 走看看