这一篇笔记介绍几种 es 的基础查询,非聚合查询。
目录如下:

  1. 数据导入
  2. 排序查询
  3. es 中的 limit 和offset
  4. 匹配字符串
  5. 匹配词组
  6. 数字精确查找
  7. es 中的或与非
  8. es 中的大小于过滤

首先,介绍一下 es 的存储方式,是以 json 这种结构化文档的形式存储数据的。

es 下有很多 index,对应于 MySQL 中的 database,
每个 index 下有很多 type,对应于 MySQL 中的 table,
再往下就是一个个的 json 字段,相当于 MySQL 中的字段。

es 的操作风格很 restful,使用 GET、PUT、POST、DELETE 来实现数据的增删改查。

比如在 kibana 中使用如下命令创建一条数据:

PUT /customer/_doc/1
{
  "name": "John Doe"
}

然后就可以以这种类似于 url 的形式查询这条数据:

GET /customer/_doc/1

1、数据导入

首先从官方文档中下载一批数据,数据地址
如果不想去复制,在文章末尾下载了该文档。

然后在服务器上使用 curl 命令导入该文档:

curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@accounts.json"

记得文件名为 accounts.json,且执行该命令的时候要在文档所在文件夹。

在 kibana 中查看数据库:

curl "localhost:9200/_cat/indices?v"

就可以在 index 那一栏下看到有 bank 这个 index 存在了。

2、排序查询

指定 index 就可以进行查询了。
首先可以使用以下语句,查询一条数据,看看数据的结构:

GET /bank/_doc/1

返回结果如下:

{
  "_index" : "bank",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "account_number" : 1,
    "balance" : 39225,
    "firstname" : "Amber",
    "lastname" : "Duke",
    "age" : 32,
    "gender" : "M",
    "address" : "880 Holmes Lane",
    "employer" : "Pyrami",
    "email" : "amberduke@pyrami.com",
    "city" : "Brogan",
    "state" : "IL"
  }
}

在返回的结果里,
_index 表示是所在的 索引名,
_type 表示所在的表名,
_source 表示的是返回的源数据结果。

接下来我们对所有数据进行查询,且对 balance 和 account_number 进行排序:

GET /bank/_search
{
  "query": {"match_all": {}},
  "sort": [
    {"balance": "desc"},
    {"account_number": "asc"}
  ]
}

语句里的 query 下是 查询的条件,
sort 是一个 list,里面包含一至多个字段,用来排序,asc 是升序,desc 是降序。

3、es 中的 limit 和offset

在每次查询返回的结果中,如果不指定 size 字段,则会默认返回最多十条数据。

es 中对应于 MySQL 中的 limitoffset 字段是 fromsize
from 从 0 开始取值。

GET /bank/_search
{
  "query": {"match_all": {}},
  "sort": [
    {"balance": "desc"},
    {"account_number": "asc"}
  ],
  "from": 1,
  "size": 2
}

4、匹配字符串

比如想查询数据中 address 字段包含 lane 或者 street 的数据,MySQL 中语法大致是:

where address like "%lane%" or address like "%street%"

在 es 中使用的语法如下:

GET /bank/_search
{
  "query": {
    "match": {
      "address": "lane street"
    }
  },
  "size": 40
}

为了看到字段中包含 street 数据,这里将 size 定为了 40,因为默认只有十条。

5、匹配词组

匹配词组的说法可能不太准确,前面我们通过 空格 将两个待选的关键词分开,表示满足这两者之一即可。

而如果我们想要完整匹配一个词组,比如官方文档示例中的 “mill lane”,则可以使用 match_phrase

GET /bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill lane"
    }
  }
}

在 MySQL 中,语法大致是:

where address like "%mill lane%"

以上的匹配都是大小写不敏感的,也就是匹配的结果中,不区分大小写。

如果想要设置大小写敏感,等我回头看到了方法再补上。

6、数字精确查找

比如想要在数据中找到 age 字段值为 35 的数据:

GET /bank/_search
{
  "query": {
    "match": {
      "age": 35
    }
  }
}

7、es 中的与或非

在 es 中的 与或非 分别是 must、should、must_not
如果是两者 或者 三者 共存,则使用 bool 将其连接在一起。

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {"match":{"age": 24}}
      ],
      "must_not": [
        {"match": {"gender": "M"}}
      ]
    }
  }
}

每一个 must 或者 must_not 都是一个 list,用于匹配多个条件。

8、es 中的大小于过滤

es 中的大小于过滤条件,使用 filterrange 关键字,其中,filter 在组合条件中与 must 等同级。

GET /bank/_search
{
  "query": {
    "bool":{
      "must": {"match_all": {}},
      "filter": {
        "range": {
          "age": {
            "gte": 21,
            "lte": 22
          }
        }
      }
    }
  }
}