ElasticSearch《二:进阶检索DSL语言》

963 阅读5分钟

:本节所有语句都是在Kibana演示

ES支持两种基本方式检索

  • 通过REST request uri 发送搜索参数 (uri +检索参数);
  • 通过REST request body 来发送它们(uri+请求体); 检索返回内容部分信息含义
  • took – 花费多少ms搜索
  • timed_out – 是否超时
  • _shards – 多少分片被搜索了,以及多少成功/失败的搜索分片
  • max_score –文档相关性最高得分
  • hits.total.value - 多少匹配文档被找到
  • hits.sort - 结果的排序key(列),没有的话按照score排序
  • hits._score - 相关得分 (not applicable when using match_all)

一:DSL领域特定语言

概念:Elasticsearch提供了一个可以执行查询的Json风格的DSL(domain-specific language领域特定语言)。这个被称为Query DSL

1.1全量查询

GET /newbank/_search

image.png

1.2带条件查询

查询address包含Lane的记录

GET /newbank/_search
{
  "query": {"match": {
    "address": "Lane"
  }}
}

image.png

1.3排序及展示

GET /newbank/_search
{
  "query": {  
    "match_all": {}
  },
  "from": 0, 
  "size": 5,
  "_source":["balance"],
  "sort": [
    {
      "account_number": {  
        "order": "desc"
      }
    }
  ]
}

image.png

  • match_all查询类型【代表查询所有的索引】,es中可以在query中组合非常多的查询类型完成复杂查询;
  • 除了query参数之外,我们可也传递其他的参数以改变查询结果,如sort,size;
  • from+size限定,完成分页功能;
  • sort排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准;

1.4query/match匹配查询

如果是非字符串,会进行精确匹配。如果是字符串,会进行全文检索

GET /newbank/_search
{
  "query": {
    "match": {
      "address": "685"
    }
  }
}

image.png

1.5query/match_phrase[不拆分匹配]

将需要匹配的值当成一整个单词(不分词)进行检索

  • match_phrase:不拆分字符串进行检索
  • 字段.keyword:必须全匹配上才检索成功
GET /newbank/_search
{
  "query": {
    "match_phrase": {
      "address": "School Lane"
    }
  }
}

image.png

1.6query/multi_math【多字段匹配】

查询state或者address中包含mill的所有记录

GET /bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",
      "fields": [
        "state","address"
        ]
    }
  }
}

image.png

1.7query/bool/must复合查询

复合语句可以合并,任何其他查询语句,包括符合语句。这也就意味着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。

  • must:必须达到must所列举的所有条件
  • must_not:必须不匹配must_not所列举的所有条件。
  • should:应该满足should所列举的条件。满足条件最好,不满足也可以,满足得分更高 如下所示,查询address里必须包含Road,并且gender不是F的所有记录
GET /bank/_search
{
  "query": {"bool": {
    "must": [
      {"match": {
        "address": "Road"
      }}
    ],"must_not": [
      {"match": {
        "gender": "F"
      }}
    ]
  }}
}

image.png

1.8query/filter【结果过滤】

  • must 贡献得分
  • should 贡献得分
  • must_not 不贡献得分
  • filter 不贡献得分 对于仅用于filtering过滤的文档。对得分没有要求的查询,建议使用filter,效率会更快,原因是elasticsearch会自动检查场景并且优化查询的执行。

查询gender不为F,且age在10到20之间的所有数据

GET /bank/_search
{
  "query": {
    "bool": {
      "must_not": [
        {"match": {
          "gender": "F"
        }}
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 10,
            "lte": 20
          }
        }
      }
    }
  }
}

从查询结果可以看的所有相关性得分都为0 image.png

1.9query/term

term和match一样。匹配某个属性的值。用法区别就是

  • 全文检索字段用match,
  • 其他非text字段匹配用term 查询balance为1650的所有记录
GET /bank/_search
{
  "query": {
    "term": {
      "balance": {
        "value": "1650"
      }
    }
  }
}

image.png

二:aggs/agg1(聚合)

聚合提供了从数据中分组和提取数据的能力。最简单的聚合方法大致等于SQL Group by和SQL聚合函数。

在elasticsearch中,执行搜索返回this(命中结果),并且同时返回聚合结果,把以响应中的所有hits(命中结果)分隔开的能力。这是非常强大且有效的,你可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果,使用一次简洁和简化的API避免网络往返。 基本语法

"aggs":{ # 聚合 
"aggs_name":{ # 这次聚合的名字,方便展示在结果集中 
"AGG_TYPE":{} # 聚合的类型(avg,term,terms)
} 
}
  • terms:看值的可能性分布,会合并锁查字段,给出计数即可
  • avg:看值的分布平均

2.1普通聚合aggs/aggName

查询address中包含Court的所有人的年龄分布以及平均年龄

GET /bank/_search
{
  "query": {"match": {
    "address": "Court"
  }
    
  },"aggs": {
    "age1": {
      "terms": {
        "field": "age",
        "size": 10
      }
    },"ageavg":{
      "avg": {
        "field": "age"
      }
    }
  }
}

image.png

2.2aggs/aggName/aggs/aggName子聚合

搜索address中包含Court的所有人的年龄分布以及平均年龄,并且求这些年龄段的这些人的平均薪资

GET /bank/_search
{
  "query": {
    "match": {
      "address": "Court"
    }
  },"aggs": {
    "aggs1": {
      "terms": {
        "field": "age"
      },"aggs": {
        "aggsAvg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

image.png

三:Mapping字段映射

GET /bank/_mapping

image.png 核心数据类型

(1)字符串

text ⽤于全⽂索引,搜索时会自动使用分词器进⾏分词再匹配 keyword 不分词,搜索时需要匹配完整的值 (2)数值型

整型: byte,short,integer,long 浮点型: float, half_float, scaled_float,double (3)日期类型:date

(4)范围型

integer_range, long_range, float_range,double_range,date_range

gt是大于,lt是小于,e是equals等于。

age_limit的区间包含了此值的文档都算是匹配。

(5)布尔: boolean

(6)二进制: binary 会把值当做经过 base64 编码的字符串,默认不存储,且不可搜索

复杂数据类型

(1)对象

  • object一个对象中可以嵌套对象。

(2)数组

  • Array

(3)嵌套类型

  • nested 用于json对象数组 注意:对于已经存在的字段映射,我们不能更新。更新必须创建新的索引,进行数据迁移。 创建映射:
PUT /newbank
{
  "mappings": {
    "properties": {
      "account_number": {
        "type": "long"
      },
      "address": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "balance": {
        "type": "long"
      },
      "city": {
        "type": "keyword"
      },
      "email": {
        "type": "keyword"
      },
      "employer": {
        "type": "keyword"
      },
      "firstname": {
        "type": "text"
      },
      "gender": {
        "type": "keyword"
      },
      "lastname": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "state": {
        "type": "keyword"
      }
    }
  }
}

es6.0以后使用如下方式进行数据迁移。

POST _reindex
{
  "source":{
      "index":"twitter"
   },
  "dest":{
      "index":"new_twitters"
   }
}

其中twitter是源索引,new_twitters是目标索引,更多知识可以参考官方文档 www.elastic.co/guide/en/el…