ElasticSearch快速入门(一)

2022-08-01 09:54:28 浏览数 (1)

前言

Elaticsearch,简称为 ES, 是一个开源的高扩展的分布式全文搜索引擎 (这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎)。与传统型关系数据库不同,Elaticsearch使用的是倒排索引,它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

例如百度、谷歌之类的搜索引擎,它们都是根据网页中的关键字生成索引的,当我们在这类搜索引擎输入关键字进行搜索时,它们会根据关键字去匹配索引,然后将索引对应的所有网页返回;除了这类搜索引擎之外,还一些非结构化的数据文本等,对于这些内容的搜索,关系型数据库搜索不是能很好的支持。而且一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段(除了wordpress,之前折腾wordpress时,把数据库删了,文章直接就没了,后面发现wordpress竟然把文章存在数据库里 == )。当进行全文检索时,需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。即使建立了索引,后期维护起来也比较麻烦,进行插入和更新操作时都会重新构建索引。 全文搜索引擎的适用场景:

  • 搜索的数据对象是大量的非结构化的文本数据。
  • 文件记录量达到数十万或数百万个甚至更多。
  • 支持大量基于交互式文本的查询。
  • 需求非常灵活的全文搜索查询。
  • 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
  • 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。

下载安装

Elasticsearch 的官方地址,下载完后直接解压;

进入 bin 文件目录,点击 elasticsearch.bat 文件启动 ES 服务

打开地址:http://localhost:9200,测试是否启动成功

RESTful

在SpringMVC中有提到过。

REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就 是 RESTful。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之 间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务 器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用 服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。 在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它 向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客 户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。

在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目 标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、POST、 PUT、DELETE,还可能包括 HEAD 和 OPTIONS。简单的理解就是,如果想要访问互联 网上的资源,就必须向资源所在的服务器发出请求,请求体中必须包含资源的网络路径,以 及对资源进行的操作(增删改查)。

第三方工具

使用Elasticsearch服务器发请求时必须包含HTTP 标准的方法,而大部分浏览器默认发送的只有 GET 和 POST 请求。所以为了能方便地进行客户端的访问,

我们可以使用Postman 网页调试工具配合使用。

Postman下载安装后,按照提示填写信息,然后随便创建一个team就可以了;

使用Elasticsearch服务器发请求时必须包含HTTP 标准的方法,而大部分浏览器默认发送的只有 GET 和 POST 请求。所以为了能方便地进行客户端的访问,

我们可以使用以下几种工具可配合使用。

  1. Kibana,Elastic官方提供的ES可视化工具
  1. Postman ,功能强大网页调试工具,可用于完成ES各种请求
  1. Chrome的ES插件
  1. elasticsearch-head,界面简陋,但是使用十分方便的ES在线可视化工具

数据格式

Elasticsearch 是面向文档型数据库,一条数据对应的就是一个文档。

与MySQL的类比:

ES 里的 Index 可以看做一个库,而 Types 相当于表,Documents 则相当于表的行。 这里 Types 的概念已经被逐渐弱化,Elasticsearch 6.X 中,一个 index 下已经只能包含一个 type,Elasticsearch 7.X 中, Type 的概念已经被删除了

用 JSON 作为文档序列化的格式,比如一条用户信息:

代码语言:javascript复制
{
 "name" : "Ahzoo",
 "age" : 18,
 "birthDate": "01/23",
 "about" : "nothing",
 "interests": [ "sports", "music" ]
}

HTTP操作

Postman

索引操作

为了方便演示RESTful风格,这里使用的是Postman进行操作,如果不用RESTful风格,可直接跳到Kibana

打开Postman,按照提示进行初始化设置;

进入Postman界面后,新建一个Collection;

创建索引

相当于关系型数据库中的创建数据库

点击右侧加号;输入一个PUT命令:

代码语言:javascript复制
PUT http://127.0.0.1:9200/shopping

然后点击Send,可以看到创建成功的提示 返回结果:

代码语言:javascript复制
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "shopping"
}

重复添加时会报错: 返回结果:

代码语言:javascript复制
{
  "error" : {
    "root_cause" : [
      {
        "type" : "resource_already_exists_exception",
        "reason" : "index [shopping/oTiQnf9UT--dwgsZ_2wBow] already exists",
        "index_uuid" : "oTiQnf9UT--dwgsZ_2wBow",
        "index" : "shopping"
      }
    ],
    "type" : "resource_already_exists_exception",
    "reason" : "index [shopping/oTiQnf9UT--dwgsZ_2wBow] already exists",
    "index_uuid" : "oTiQnf9UT--dwgsZ_2wBow",
    "index" : "shopping"
  },
  "status" : 400
}
查询索引

输入一个GET命令,来查询所有索引;(cat 表示查看的意思,indices 表示索引,相当于像 MySQL 中的 show tables)

代码语言:javascript复制
GET http://127.0.0.1:9200/_cat/indices?v

返回结果:

代码语言:javascript复制
health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .geoip_databases                fjfmnkm2RZKMHtGbBQGweg   1   0         41           39     40.1mb         40.1mb
green  open   .kibana_7.15.0_001              mKyI2n3oSaK-U7-BIepohA   1   0         51            5      2.3mb          2.3mb
green  open   .apm-custom-link                4m9W5TxCRJSs8I6GqDepMw   1   0          0            0       208b           208b
green  open   .apm-agent-configuration        731dsjx0TaWdnmGqyKBvQQ   1   0          0            0       208b           208b
green  open   .kibana-event-log-7.15.0-000001 2__Yx8BARWGwOgCarYgezA   1   0          1            0        6kb            6kb
green  open   .kibana_task_manager_7.15.0_001 bWnZfG6aQPyCXa8j23Mimw   1   0         15         3825    540.5kb        540.5kb
yellow open   shopping                        VxYeY2FBS6a8wZxgWEdGtQ   1   1          0            0       208b           208b

查询单个索引

代码语言:javascript复制
GET http://127.0.0.1:9200/shopping

返回结果:

代码语言:javascript复制
{
    "shopping": {
        "aliases": {},
        "mappings": {},
        "settings": {
            "index": {
                "routing": {
                    "allocation": {
                        "include": {
                            "_tier_preference": "data_content"
                        }
                    }
                },
                "number_of_shards": "1",
                "provided_name": "shopping",
                "creation_date": "1633513773067",
                "number_of_replicas": "1",
                "uuid": "VxYeY2FBS6a8wZxgWEdGtQ",
                "version": {
                    "created": "7150099"
                }
            }
        }
    }
}
删除索引
代码语言:javascript复制
DELETE http://127.0.0.1:9200/shopping

返回结果:

代码语言:javascript复制
{
  "acknowledged" : true
}
文档操作
创建文档

这里的文档就相当于MySQL中的表中的数据

发送一个POST请求,创建文档,文档的格式为JSON:

  • POST

选择POST请求(由于此处没有指定ID为非幂等性操作,所以只能用POST):

简单理解幂等性:多次操作与一次操作的结果相同,即为幂等性操作;反之 此例中由于没有指定ID,所以ID为随机生成,导致多次操作与一次操作的结果不同

代码语言:javascript复制
POST http://127.0.0.1:9200/shopping/_doc

输入请求体:点击Body,点击raw,格式选择JSON,并在输入框输入请求体(请求完成后记得把请求体删除,否则遇到不需要请求体的命令时会报错)

代码语言:javascript复制
{
 "title":"HUAWEI Mate 40 Pro",
 "category":"华为手机",
 "images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
 "price":6299
}

然后点击Send发送请求;

返回结果(附解释):

代码语言:javascript复制
{
    "_index"【索引】: "shopping",
    "_type"【类型-文档】: "_doc",
    "_id"【唯一标识】: "qHRAVXwBGcQwpwap0CcF", //可以类比为 MySQL 中的主键,随机生成
    "_version"【版本】: 1,
    "result"【结果】: "created",//这里的 create 表示创建成功
    "_shards"【分片】: {
        "total"【分片 - 总数】: 2,
        "successful"【分片 - 成功】: 1,
        "failed"【分片 - 失败】: 0
    },
    "_seq_no": 0,
    "_primary_term": 1
}
  • PUT/POST

上面的数据创建后,由于没有指定数据唯一性标识(ID)(也就是主键),默认情况下,ES 服务器会随机生成一个。 如果想要自定义唯一性标识,需要在创建时指定(此时就变成了幂等性操作,因此可以使用POST和PUT两种请求方式):

代码语言:javascript复制
POST/PUT http://127.0.0.1:9200/shopping/_doc/1

请求体:(请求完成后记得把请求体删除,否则遇到不需要请求体的命令时会报错)

代码语言:javascript复制
{
 "title":"HUAWEI Mate 40 Pro",
 "category":"华为手机",
 "images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
 "price":6299
}

返回结果:

代码语言:javascript复制
{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1", // 可以看到ID为指定的 1
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 1,
    "_primary_term": 1
}
查看文档
  • 通过主键(ID)查询,此处的1为刚才创建的ID
代码语言:javascript复制
GET http://127.0.0.1:9200/shopping/_doc/1

返回结果:

代码语言:javascript复制
{

  "_index": "shopping",

  "_type": "_doc",

  "_id": "1",

  "_version": 2,

  "_seq_no": 2,

  "_primary_term": 1,

  "found": **true**,

  "_source": {

​    "title": "HUAWEI Mate 40 Pro",

​    "category": "华为手机",

​    "images": "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",

​    "price": 6299

  }

}
  • 通过_search查询目标索引全部数据
代码语言:javascript复制
http://127.0.0.1:9200/shopping/_search
代码语言:javascript复制
{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
            {
                "_index": "shopping",
                "_type": "_doc",
                "_id": "qHRAVXwBGcQwpwap0CcF",
                "_score": 1.0,
                "_source": {
                    "title": "HUAWEI Mate 40 Pro",
                    "category": "华为手机",
                    "images": "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
                    "price": 6299
                }
            },
            {
                "_index": "shopping",
                "_type": "_doc",
                "_id": "1",
                "_score": 1.0,
                "_source": {
                    "title": "HUAWEI Mate 40 Pro",
                    "category": "华为手机",
                    "images": "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
                    "price": 6299
                }
            }
        ]
    }
}
修改文档
  • 全量修改
代码语言:javascript复制
POST/PUT http://127.0.0.1:9200/shopping/_doc/1

请求体:(请求完成后记得把请求体删除,否则遇到不需要请求体的命令时会报错)

代码语言:javascript复制
{
 "title":"HUAWEI Mate 40",
 "category":"华为手机",
 "images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
 "price":6099
}

点击Send发送请求:

返回结果:

代码语言:javascript复制
{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1",
    "_version"【版本】: 3,
    "result"【结果】: "updated",// updated 表示数据被更新
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 3,
    "_primary_term": 1
}
  • 局部修改(非幂等性)
代码语言:javascript复制
POST http://127.0.0.1:9200/shopping/_update/1

请求体:

代码语言:javascript复制
{ 
    "doc": {
        "category":"国产手机" // 点名要修改的字段为"category"
        //这里可以写其它需要修改的字段
    }
}

返回结果:

代码语言:javascript复制
{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1",
    "_version": 2,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 16,
    "_primary_term": 1
}
删除文档
  • 通过ID删除
代码语言:javascript复制
DELETE http://127.0.0.1:9200/shopping/_doc/1

返回结果:

代码语言:javascript复制
{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1",
    "_version": 5,
    "result": "deleted",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 5,
    "_primary_term": 1
}
  • 通过条件删除
代码语言:javascript复制
POST http://127.0.0.1:9200/shopping/_delete_by_query

请求体:

代码语言:javascript复制
{
 "query":{
    "match":{
        "price":6299
    }
 }
}

返回结果:

代码语言:javascript复制
{
    "took"【请求时间】: 24,
    "timed_out"【是否超时】: false,
    "total"【总数】: 3,
    "deleted"【删除数量】: 3,
    "batches": 1,
    "version_conflicts": 0,
    "noops": 0,
    "retries": {
        "bulk": 0,
        "search": 0
    },
    "throttled_millis": 0,
    "requests_per_second": -1.0,
    "throttled_until_millis": 0,
    "failures": []
}

同理如果要删除索引下全部数据,只需要改请求体条件即可:

代码语言:javascript复制
{
 "query": {
    "match_all": {}
  }
}

Kibana

打开Kibana的bin路径下的kibana.bat启动Kibana;

然后浏览器访问5601端口,点击Explore on my own;

在左侧菜单找到Dev Tools;

索引操作
创建索引

相当于关系型数据库中的创建数据库

输入一个PUT命令:

代码语言:javascript复制
PUT shopping

错误写法(不能有空行):

代码语言:javascript复制
PUT shopping

点击代码右侧的启动按钮,可以在右侧看到创建成功的提示 返回结果:

代码语言:javascript复制
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "shopping"
}

重复添加时会报错: 返回结果:

代码语言:javascript复制
{
  "error" : {
    "root_cause" : [
      {
        "type" : "resource_already_exists_exception",
        "reason" : "index [shopping/oTiQnf9UT--dwgsZ_2wBow] already exists",
        "index_uuid" : "oTiQnf9UT--dwgsZ_2wBow",
        "index" : "shopping"
      }
    ],
    "type" : "resource_already_exists_exception",
    "reason" : "index [shopping/oTiQnf9UT--dwgsZ_2wBow] already exists",
    "index_uuid" : "oTiQnf9UT--dwgsZ_2wBow",
    "index" : "shopping"
  },
  "status" : 400
}
查询索引

输入一个GET命令,来查询所有索引;(cat 表示查看的意思,indices 表示索引,相当于像 MySQL 中的 show tables)

代码语言:javascript复制
GET _cat/indices?v

返回结果:

代码语言:javascript复制
health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .geoip_databases                fjfmnkm2RZKMHtGbBQGweg   1   0         41           39     40.1mb         40.1mb
green  open   .kibana_7.15.0_001              mKyI2n3oSaK-U7-BIepohA   1   0         51            3      2.3mb          2.3mb
green  open   .apm-custom-link                4m9W5TxCRJSs8I6GqDepMw   1   0          0            0       208b           208b
green  open   .apm-agent-configuration        731dsjx0TaWdnmGqyKBvQQ   1   0          0            0       208b           208b
green  open   .kibana-event-log-7.15.0-000001 2__Yx8BARWGwOgCarYgezA   1   0          1            0        6kb            6kb
green  open   .kibana_task_manager_7.15.0_001 bWnZfG6aQPyCXa8j23Mimw   1   0         15         2124    286.4kb        286.4kb
yellow open   shopping                        pjEDILI4TjCq1zG2rGfiww   1   1          0            0       208b           208b

可以看到ElasticSearch请求方式用小写也能执行,但是左侧会报错误提醒

查询单个索引

代码语言:javascript复制
GET shopping

返回结果:

代码语言:javascript复制
{
  "shopping" : {
    "aliases" : { },
    "mappings" : { },
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "1",
        "provided_name" : "shopping",
        "creation_date" : "1633512085101",
        "number_of_replicas" : "1",
        "uuid" : "pjEDILI4TjCq1zG2rGfiww",
        "version" : {
          "created" : "7150099"
        }
      }
    }
  }
}
删除索引
代码语言:javascript复制
DELETE shopping

返回结果:

代码语言:javascript复制
{
  "acknowledged" : true
}
文档操作
创建文档

这里的文档就相当于MySQL中的表中的数据

发送一个POST请求,创建文档,文档的格式为JSON:

  • POST

选择POST请求(由于此处没有指定ID为非幂等性操作,所以只能用POST):

简单理解幂等性:多次操作与一次操作的结果相同,即为幂等性操作;反之 此例中由于没有指定ID,所以ID为随机生成,导致多次操作与一次操作的结果不同

代码语言:javascript复制
POST shopping/_doc 
{
 "title":"HUAWEI Mate 40 Pro",
 "category":"华为手机",
 "images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
 "price":6299
}

点击右侧运行按钮运行

返回结果(附解释):

代码语言:javascript复制
{
    "_index"【索引】: "shopping",
    "_type"【类型-文档】: "_doc",
    "_id"【唯一标识】: "qXSbVXwBGcQwpwaptCcq", //可以类比为 MySQL 中的主键,随机生成
    "_version"【版本】: 1, //对数据的操作,都会更新版本
    "result"【结果】: "created",//这里的 create 表示创建成功
    "_shards"【分片】: {
        "total"【分片 - 总数】: 2,
        "successful"【分片 - 成功】: 1,
        "failed"【分片 - 失败】: 0
    },
    "_seq_no": 6,
    "_primary_term": 1
}
  • PUT/POST

上面的数据创建后,由于没有指定数据唯一性标识(ID)(也就是主键),默认情况下,ES 服务器会随机生成一个。 如果想要自定义唯一性标识,需要在创建时指定(此时就变成了幂等性操作,因此可以使用POST和PUT两种请求方式)

代码语言:javascript复制
PUT shopping/_doc/1
{
 "title":"HUAWEI Mate 40 Pro",
 "category":"华为手机",
 "images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
 "price":6299
}
代码语言:javascript复制
POST shopping/_doc/1
{
 "title":"HUAWEI Mate 40 Pro",
 "category":"华为手机",
 "images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
 "price":6299
}

返回结果:

代码语言:javascript复制
{
    "_index": "shopping",
    "_type": "_doc",
    "_id": "1", // 可以看到ID为指定的 1
    "_version": 2,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 8,
    "_primary_term": 1
}
查看文档
  • 通过主键(ID)查询,此处的1为刚才创建的ID
代码语言:javascript复制
GET shopping/_doc/1

返回结果:

代码语言:javascript复制
{
  "_index" : "shopping",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 8,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "title" : "HUAWEI Mate 40 Pro",
    "category" : "华为手机",
    "images" : "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
    "price" : 6299
  }
}
  • 通过_search查询目标索引全部数据
代码语言:javascript复制
GET shopping/_search
代码语言:javascript复制
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "shopping",
        "_type" : "_doc",
        "_id" : "qHRAVXwBGcQwpwap0CcF",
        "_score" : 1.0,
        "_source" : {
          "title" : "HUAWEI Mate 40 Pro",
          "category" : "华为手机",
          "images" : "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
          "price" : 6299
        }
      },
      {
        "_index" : "shopping",
        "_type" : "_doc",
        "_id" : "qXSbVXwBGcQwpwaptCcq",
        "_score" : 1.0,
        "_source" : {
          "title" : "HUAWEI Mate 40 Pro",
          "category" : "华为手机",
          "images" : "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
          "price" : 6299
        }
      },
      {
        "_index" : "shopping",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "title" : "HUAWEI Mate 40 Pro",
          "category" : "华为手机",
          "images" : "https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
          "price" : 6299
        }
      }
    ]
  }
}
修改文档
  • 全量修改

请求体:(请求完成后记得把请求体删除,否则遇到不需要请求体的命令时会报错)

代码语言:javascript复制
PUT shopping/_doc/1
{
  "title":"HUAWEI Mate 40",
  "category":"华为手机",
  "images":"https://res.vmallres.com/pimages//product/6941487225231/428_428_797B0D9B0E6215FA6F6E7D20C3856D594385808C2EB3B3C2mp.png",
  "price":6099
}

返回结果:

代码语言:javascript复制
{
  "_index" : "shopping",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "result" : "updated", // updated 表示数据被更新
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 9,
  "_primary_term" : 1
}
  • 局部修改(非幂等性)
代码语言:javascript复制
POST http://127.0.0.1:9200/shopping/_update/1

请求体:

代码语言:javascript复制
POST /shopping/_update/1
{ 
    "doc": {
        "title":"华为 Mate 40",//点名要修改的字段为"title"
        "category":"国产手机" //点名要修改的字段为"category"
        //这里可以写其它需要修改的字段
    }
}

返回结果

代码语言:javascript复制
{
  "_index" : "shopping",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 4,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 10,
  "_primary_term" : 1
}
删除文档
  • 通过ID删除
代码语言:javascript复制
DELETE /shopping/_doc/1

返回结果:

代码语言:javascript复制
{
  "_index" : "shopping",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 5,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 11,
  "_primary_term" : 1
}
  • 通过条件删除
代码语言:javascript复制
POST /shopping/_delete_by_query
{
   "query":{
    "match":{
        "price":6299
    }
 }
}

返回结果:

代码语言:javascript复制
{
  "took" 【请求时间】: 521,
  "timed_out" 【是否超时】: false,
  "total" 【总数】: 2,
  "deleted" 【删除数量】: 2,
  "batches" : 1,
  "version_conflicts" : 0,
  "noops" : 0,
  "retries" : {
    "bulk" : 0,
    "search" : 0
  },
  "throttled_millis" : 0,
  "requests_per_second" : -1.0,
  "throttled_until_millis" : 0,
  "failures" : [ ]
}

同理如果要删除索引下全部数据,只需要改请求体条件即可:

代码语言:javascript复制
{
 "query": {
    "match_all": {}
  }
}

对比

一图简单对比Postman和Kibana使用ES命令方式区别:

由于后面示例都是用的Kibana,继续用Postman的可自行参照此图,根据示例中的Kibana进行类比

映射关系

索引库(index)中的映射类似于数据库(database)中的表结构(table)。 创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型 下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。

映射数据说明:

  • 字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
  • type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的:
    • String 类型,又分两种: text:可分词
    • keyword:不可分词,数据会作为完整字段进行匹配
  • Numerical:数值类型,分两类
    • 基本数据类型:long、integer、short、byte、double、float、half_float
    • 浮点数的高精度类型:scaled_float
  • Date:日期类型
  • Array:数组类型
  • Object:对象
  • index:是否索引,默认为 true,也就是说你不进行任何配置,所有字段都会被索引。
    • true:字段会被索引,则可以用来进行搜索
    • false:字段不会被索引,不能用来搜索
  • store:是否将数据进行独立存储,默认为 false 原始的文本会存储在_source 里面,默认情况下其他提取出来的字段都不是独立存储 的,是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置 “store”: true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用 更多的空间,所以要根据实际业务需求来设置。
  • analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器
创建映射关系
  • 方法一:

首先创建索引

代码语言:javascript复制
PUT student

然后创建映射关系

代码语言:javascript复制
PUT student/_mapping
{
 "properties": {
  "name":{
     "type": "text",
     "index": true
  },
  "nickname":{
     "type": "text",
     "index": true
  },
  "sex":{
     "type": "keyword",
     "index": true
   },
   "age":{
     "type": "long",
     "index": false
   }
 }
}

返回结果:

代码语言:javascript复制
{
  "acknowledged" : true
}
  • 方法二: 直接创建索引并与映射关联
代码语言:javascript复制
PUT student2
{
  "settings": {}, 
  "mappings": {
   "properties": {
    "name":{
      "type": "text",
       "index": true
   },
   "nickname":{
       "type": "keyword",
       "index": true
   },
   "sex":{
       "type": "keyword",
       "index": true
    },
    "age":{
      "type": "long",
      "index": false
    }
   }
  }
}

返回结果:

代码语言:javascript复制
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "student2"
}
查看映射关系
代码语言:javascript复制
GET student/_mapping

返回结果:

代码语言:javascript复制
{
  "student" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "long",
          "index" : false
        },
        "name" : {
          "type" : "text"
        },
        "nickname" : {
          "type" : "text"
        },
        "sex" : {
          "type" : "keyword"
        }
      }
    }
  }
}

高级查询

为了方便演示,这里不使用系统自动给的映射,而是自行创建映射

代码语言:javascript复制
PUT phone
{   
  "settings": {},
  "mappings": {    
    "properties": {   
      "name":{     
        "type": "text",     
        "index": true        
      },   
      "vendor":{
        "type": "keyword",     
        "index": true   
      },   
      "pid":{     
        "type": "long",
        "index": false
      },
      "price":{     
        "type": "long",
        "index": true
      },
      "content":{     
        "type": "text",
        "index": true
      },
      "area":{     
        "type": "keyword",
        "index": true
      }
    }   
  } 
} 

创建完映射后,创建数据

代码语言:javascript复制
POST /phone/_doc/1001  //这里的_doc即为文档类型,ElasticSearch 7.0已不支持自定义,只能为_doc
{ 
  "name":"小米手机", 
  "vendor":"小米",
  "pid":"1001",
  "price":3999 ,
  "content":"MIUI Based on Android OS",
  "area": "China"
}

POST /phone/_doc/1002
{ 
  "name":"小米手机Pro", 
  "vendor":"小米",
  "pid":"1002",
  "price":4999 ,
  "content":"MIUI Not based on Harmony OS",
  "area": "China"
}

POST /phone/_doc/1003
{ 
  "name":"华为手机", 
  "vendor":"华为",、
  "pid":"1003",
  "price":4488 ,
  "content":"HarmonyOS Based on Harmony OS",
  "area": "China"
}
POST /phone/_doc/1004
{ 
  "name":"华为手机", 
  "vendor":"华为",
  "pid":"1004",
  "price":6488,
  "content":"HarmonyOS Not based on Android OS",
  "area": "China"
}

POST /phone/_doc/1005
{ 
  "name":"苹果手机", 
  "vendor":"Apple",
  "pid":"1005",
  "price":5199,
  "content":"IOS Not based on Android OS",
  "area": "American"
}
POST /phone/_doc/1006
{ 
  "name":"苹果手机", 
  "vendor":"Apple",
  "pid":"1006",
  "price":7999,
  "content":"IOS Not based on Harmony OS",
  "area": "American"
}
全量查询(match_all)
代码语言:javascript复制
GET phone/_search
{   
  "query": { // "query":这里的 query 代表一个查询对象,里面可以有不同的查询属性
    "match_all": {}   // "match_all":查询类型,例如:match_all(代表查询所有), match,term , range 等等;
    // "match_all":{查询条件}:match_all下写查询条件,根据类型的不同,写法也有差异
  } 
} 

代码语言:javascript复制
{
  "took" 【查询花费时间,单位毫秒】: 0,
  "timed_out"【是否超时】 : false,
  "_shards"【分片信息】 : {
    "total"【总数】 : 1,
    "successful"【成功】 : 1,
    "skipped" 【忽略】: 0,
    "failed"【失败】 : 0
  },
  "hits"【搜索命中结果】 : {
    "total" 【搜索条件匹配的文档总数】: {
      "value"【总命中计数的值】 : 6,
      "relation"【计数规则】 : "eq" //eq 表示计数准确, gte 表示计数不准确
    },
    "max_score" 【匹配度分值】: 1.0,
    "hits" 【命中结果集合】: [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 1.0,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 1.0,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 1.0,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : 1.0,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1004",
          "price" : 6488,
          "content" : "HarmonyOS Not based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1005",
        "_score" : 1.0,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1005",
          "price" : 5199,
          "content" : "IOS Not based on Android OS",
          "area" : "American"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1006",
        "_score" : 1.0,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1006",
          "price" : 7999,
          "content" : "IOS Not based on Harmony OS",
          "area" : "American"
        }
      }
    ]
  }
}
匹配查询(match)

match 匹配类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是 or 的关系 1)直接通过请求路径查询(不推荐,中文容易出现乱码)

代码语言:javascript复制
GET phone/_search?q=content:OS Android Not on

返回结果:

代码语言:javascript复制
{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 6,
      "relation" : "eq"
    },
    "max_score" : 1.2530423,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : 1.2530423,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1004",
          "price" : 6488,
          "content" : "HarmonyOS Not based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1005",
        "_score" : 1.2530423,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1005",
          "price" : 5199,
          "content" : "IOS Not based on Android OS",
          "area" : "American"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 0.88390386,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 0.5761833,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1006",
        "_score" : 0.5761833,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1006",
          "price" : 7999,
          "content" : "IOS Not based on Harmony OS",
          "area" : "American"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 0.15571001,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        }
      }
    ]
  }
}

查询条件被自动分词,所有content字段中包含“OS、Android、Not、on”的文档均会被检索出来

2)通过请求体查询

代码语言:javascript复制
GET phone/_search
{   
  "query": {     
    "match": {
      "content": "OS Android Not on"
    }   
  } 
} 

返回结果和上面一样 为了更直观的显示我们可以使用Search Profiler进行查询:

可以很直观的看到查询条件被分成了四个字段“OS、Android、Not、on”

测试text类型映射:

代码语言:javascript复制
GET phone/_search
{   
  "query": {     
    "match": {
      "name": "华果"
    }   
  } 
} 

返回结果:

代码语言:javascript复制
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0467482,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 1.0467482,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : 1.0467482,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1004",
          "price" : 6488,
          "content" : "HarmonyOS Not based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1005",
        "_score" : 1.0467482,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1005",
          "price" : 5199,
          "content" : "IOS Not based on Android OS",
          "area" : "American"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1006",
        "_score" : 1.0467482,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1006",
          "price" : 7999,
          "content" : "IOS Not based on Harmony OS",
          "area" : "American"
        }
      }
    ]
  }
}

查询字段中的华和果自动被分词了,因此所有name中包含华和果的文档全被检索出来了

同样可以看到关键词被分成了华和果两个字段

测试keyword类型映射:

代码语言:javascript复制
GET phone/_search
{   
  "query": {     
    "match": {
      "vendor": "小华"
    }   
  } 
} 

返回结果(未查到符合要求文档):

代码语言:javascript复制
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

可以看到由于vendor字段被设置了keyword映射,所以查询关键词并没有被分词;所以必须输入该字段的完整值进行查询

代码语言:javascript复制
GET phone/_search
{   
  "query": {     
    "match": {
      "vendor": "小米"
    }   
  } 
} 

返回结果:

代码语言:javascript复制
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0296195,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 1.0296195,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 1.0296195,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        }
      }
    ]
  }
}

测试index为false(不能被检索):

代码语言:javascript复制
GET phone/_search
{   
  "query": {     
    "match": {
      "pid": "1001"
    }   
  } 
} 

返回结果:(提示错误信息)

代码语言:javascript复制
{
  "error" : {
    "root_cause" : [
      {
        "type" : "query_shard_exception",
        "reason" : "failed to create query: Cannot search on field [pid] since it is not indexed.",
        "index_uuid" : "b4aDx_95SMC49YIjLsLwrw",
        "index" : "phone"
      }
    ],
    "type" : "search_phase_execution_exception",
    "reason" : "all shards failed",
    "phase" : "query",
    "grouped" : true,
    "failed_shards" : [
      {
        "shard" : 0,
        "index" : "phone",
        "node" : "a7zlNhivS7iCgDBR91d53Q",
        "reason" : {
          "type" : "query_shard_exception",
          "reason" : "failed to create query: Cannot search on field [pid] since it is not indexed.",
          "index_uuid" : "b4aDx_95SMC49YIjLsLwrw",
          "index" : "phone",
          "caused_by" : {
            "type" : "illegal_argument_exception",
            "reason" : "Cannot search on field [pid] since it is not indexed."
          }
        }
      }
    ]
  },
  "status" : 400
}
字段匹配查询(multi_match)

multi_match 与match 的区别就是它可以在多个字段中进行查询

代码语言:javascript复制
GET phone/_search
{   
  "query": {
    "multi_match": {     
      "query": "华MIUI",
      "fields": ["name", "content"]
   } 
  }
} 

查询在name和content字段中包含华和MIUI的文档

返回结果:

代码语言:javascript复制
{
  "took" : 14,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0816789,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 1.0816789,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 1.0467482,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : 1.0467482,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1004",
          "price" : 6488,
          "content" : "HarmonyOS Not based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 1.0054247,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        }
      }
    ]
  }
}
关键字精确查询(term)

term 查询,精确的关键词匹配查询,不对查询条件进行分词。

代码语言:javascript复制
GET phone/_search
{   
  "query": {
    "term": {     
      "name": {         
        "value": "小米手机"
      } 
    } 
  }
}

返回结果:(未查询到)

代码语言:javascript复制
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

由于text类型默认会被自动分词,所以存入name字段的值:“小米手机”会被自动分成“小、米、手、机”四个字,因此当我们进行精确匹配查询“小米手机”时就会查询不到;只有当查询“小、米、手、机”四个字的任意字时才会匹配到;如果name字段被设为keyword映射,则只有当查询的关键词为“小米手机”时才会进行匹配

多关键字精确查询(terms)

terms查询和term查询的区别是它可以指定多值进行匹配查询,并且只需要匹配一个值即为满足查询条件;类似于mysql 的in 。

代码语言:javascript复制
GET phone/_search
{   
  "query": {
    "terms": {     
      "vendor": ["小米", "华为"] 
    } 
  }
}

返回结果:

代码语言:javascript复制
{
  "took" : 18,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 1.0,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 1.0,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 1.0,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : 1.0,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1004",
          "price" : 6488,
          "content" : "HarmonyOS Not based on Android OS",
          "area" : "China"
        }
      }
    ]
  }
}
指定查询字段(_source)

默认情况下,ElasticSearch会将保存在_source中的所有字段都返回。因此我们可以自定义返回的字段

代码语言:javascript复制
GET phone/_search
{   
  "_source": ["name", "area"],
  "query": {     
    "match": {
      "name": "小华"
    }   
  } 
} 

设置_source只返回name和area字段

返回结果:

代码语言:javascript复制
{
  "took" : 18,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0467482,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 1.0467482,
        "_source" : {
          "area" : "China",
          "name" : "小米手机"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 1.0467482,
        "_source" : {
          "area" : "China",
          "name" : "华为手机"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : 1.0467482,
        "_source" : {
          "area" : "China",
          "name" : "华为手机"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 0.9517491,
        "_source" : {
          "area" : "China",
          "name" : "小米手机Pro"
        }
      }
    ]
  }
}
过滤字段(includes/excludes)

includes:来指定想要显示的字段

excludes:来指定不想要显示的字段 返回结果: boolmustmust_notshould

代码语言:javascript复制
GET phone/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "area": "China"
        }
      },
      "must_not": {
        "match": {
          "content": "abc"
        }
      },
      "should": {
        "match": {
          "vendor": "华为"
        }
      }
    }
  }
}
代码语言:javascript复制
{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.4714522,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 1.4714522,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : 1.4714522,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1004",
          "price" : 6488,
          "content" : "HarmonyOS Not based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 0.44183272,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 0.44183272,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        }
      }
    ]
  }
}

可以看到满足must条件的华为和小米均被查了出来,而符合should要求的华为优先级较高,被排在了前面

范围查询(range)

range 查询找出那些落在指定区间内的数字或者时间。range 查询允许以下字符

操作符

说明

gt

>

gte

>=

lt

<

lte

<=

代码语言:javascript复制
GET phone/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 4000,
        "lte": 5000
      }
    }
  }
}

返回结果:

代码语言:javascript复制
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 1.0,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 1.0,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        }
      }
    ]
  }
}
模糊查询(wildcard)

模糊查询效率较慢,因此不推荐使用;和大部分模糊匹配一样,使用*或者?进行占位替代; ​

代码语言:javascript复制
GET phone/_search
{
  "query": {
    "wildcard": {
      "area": {
        "value": "Am*"
      }
    }
  }
}

返回结果:

代码语言:javascript复制
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1005",
        "_score" : 1.0,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1005",
          "price" : 5199,
          "content" : "IOS Not based on Android OS",
          "area" : "American"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1006",
        "_score" : 1.0,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1006",
          "price" : 7999,
          "content" : "IOS Not based on Harmony OS",
          "area" : "American"
        }
      }
    ]
  }
}

因为是模糊查询,所以不受keyword映射影响,但是仍然会受到分词器的影响,比如下面实例中的模糊查询name为“小米”的文档,而上面示例已经说了,“小米手机”已经被分词成了四个独立的字,因此通过“小米”去模糊查询,仍然是查询不到的

代码语言:javascript复制
GET phone/_search
{
  "query": {
    "wildcard": {
      "name": {
        "value": "小米"
      }
    }
  }
}
单字段排序(sort)

sort 可以按照不同的字段进行排序,并且通过order 指定排序的方式(desc 降序,asc升序)。

代码语言:javascript复制
GET phone/_search
{   
  "query": {
    "match": {"area": "China"}
  },
  "sort": {     
    "price": {
      "order": "desc"
    }   
  } 
} 

返回结果:

代码语言:javascript复制
{
  "took" : 15,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : null,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1004",
          "price" : 6488,
          "content" : "HarmonyOS Not based on Android OS",
          "area" : "China"
        },
        "sort" : [
          6488
        ]
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : null,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        },
        "sort" : [
          4999
        ]
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : null,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        },
        "sort" : [
          4488
        ]
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : null,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        },
        "sort" : [
          3999
        ]
      }
    ]
  }
}
多字段排序(sort)

为方便测试,添加一个只有ID不同的数据:

代码语言:javascript复制
POST /phone/_doc/1007
{ 
  "name":"小米手机Pro", 
  "vendor":"小米",
  "pid":"1007",
  "price":4999 ,
  "content":"MIUI Not based on Harmony OS",
  "area": "China"
}

开始测试:

代码语言:javascript复制
GET phone/_search
{   
  "query": {
    "match": {"name": "小米"}
  },
  "sort": [
    {
      "price": {
        "order": "desc"
      }   
    },
    {
      "_id": {
        "order": "asc"
      }
    }
  ]
} 

先按价格降序,然后按_id升序

返回结果:

代码语言:javascript复制
{
  "took" : 18,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : null,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        },
        "sort" : [
          4999,
          "1002"
        ]
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1007",
        "_score" : null,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1007",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        },
        "sort" : [
          4999,
          "1007"
        ]
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : null,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        },
        "sort" : [
          3999,
          "1001"
        ]
      }
    ]
  }
}

测试完成后,删除刚刚添加的数据 ​

高亮查询(highlight)

Elasticsearch 可以对查询内容中的关键字部分,进行标签和样式(高亮)的设置。 在使用match 查询的同时,加上一个highlight 属性(可以不设置,不设置则为默认值):

pre_tags:前置标签 (默认为em标签)

post_tags:后置标签 (默认为em标签)

fields:需要高亮的字段

title:这里声明title 字段需要高亮,后面可以为这个字段设置特有配置

返回结果:

代码语言:javascript复制
{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.699713,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 1.699713,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        },
        "highlight" : {
          "name" : [
            "<font color='red'>小</font><font color='red'>米</font>手机"
          ]
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 1.5478239,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        },
        "highlight" : {
          "name" : [
            "<font color='red'>小</font><font color='red'>米</font>手机Pro"
          ]
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1007",
        "_score" : 1.5478239,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1007",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        },
        "highlight" : {
          "name" : [
            "<font color='red'>小</font><font color='red'>米</font>手机Pro"
          ]
        }
      }
    ]
  }
}

因为是html语法,所以返回结果里面只有文字,而不是直接显示效果

分页查询(from)

from:当前页的起始索引,默认从0 开始。 from = (页数 - 1) * size 【即from为0时,为第一页,以此类推】 size:每页显示多少条

代码语言:javascript复制
GET phone/_search
{   
  "query": {
    "match_all": {}
  },
  "sort": {
    "price": {
      "order": "asc"
    }
  },
  "from": 0,
  "size": 2
} 

返回结果:

代码语言:javascript复制
{
  "took" : 10,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 7,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : null,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        },
        "sort" : [
          3999
        ]
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : null,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        },
        "sort" : [
          4488
        ]
      }
    ]
  }
}
聚合查询(aggs)

聚合允许使用者对es文档进行统计分析,类似与MySQL中的group by

度量聚合

例如取最大值(max)、最小值(min)、平均值(avg)、总数(count)、 去重后求总数(cardinality)、返回所有度量类型的统计(stats)等等。

代码语言:javascript复制
GET phone/_search
{
  "aggs": { //aggs表示聚合操作
    "sum_price": { //sum_price为自定义的分组名 
      "sum": { //sum表示求和
        "field": "price" //分组字段:price
      }
    }
  }
}

返回结果:

代码语言:javascript复制
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 6,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1001",
        "_score" : 1.0,
        "_source" : {
          "name" : "小米手机",
          "vendor" : "小米",
          "pid" : "1001",
          "price" : 3999,
          "content" : "MIUI Based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1002",
        "_score" : 1.0,
        "_source" : {
          "name" : "小米手机Pro",
          "vendor" : "小米",
          "pid" : "1002",
          "price" : 4999,
          "content" : "MIUI Not based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1003",
        "_score" : 1.0,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1003",
          "price" : 4488,
          "content" : "HarmonyOS Based on Harmony OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1004",
        "_score" : 1.0,
        "_source" : {
          "name" : "华为手机",
          "vendor" : "华为",
          "pid" : "1004",
          "price" : 6488,
          "content" : "HarmonyOS Not based on Android OS",
          "area" : "China"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1005",
        "_score" : 1.0,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1005",
          "price" : 5199,
          "content" : "IOS Not based on Android OS",
          "area" : "American"
        }
      },
      {
        "_index" : "phone",
        "_type" : "_doc",
        "_id" : "1006",
        "_score" : 1.0,
        "_source" : {
          "name" : "苹果手机",
          "vendor" : "Apple",
          "pid" : "1006",
          "price" : 7999,
          "content" : "IOS Not based on Harmony OS",
          "area" : "American"
        }
      }
    ]
  },
  "aggregations" : {
    "max_price" : {
      "value" : 33172.0
    }
  }
}

在查询结果底部的aggregations字段中可以看到得到的相加结果为33172.0

桶聚合查询

在已有的分组条件下再进行聚合即为桶聚合,相当于MySQL中的group by 语句;桶聚合返回很多子集,并限定输入数据到一个特殊的叫做桶的子集中。可以把桶聚合想象成 类似切面功能的东西。

  • term聚合:词条的聚合

terms聚合为字段中每个词条返回一个桶。允许你生成字段每个值的统计;

  • range聚合和date range聚合

范围聚合和时间范围聚合

  • 桶嵌套

多个聚合的嵌套即为桶嵌套

后记

  • Elasticsearch 是使用 java 开发的,7.8 版本及以上需要 JDK 版本 1.8 以上,默认安装包带有 jdk 环境,如果系统配置了JDK环境变量,会默认使用系统配置的 JDK,如果没有配置使用自带的 JDK,一般建议使用系统配置的 JDK。
  • 双击启动窗口闪退,通过路径访问追踪错误,如果是“空间不足”,可以尝试修改config/jvm.options 配置文件
代码语言:javascript复制
# 设置 JVM 初始内存为 1G。此值可以设置与-Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存 # Xms represents the initial size of total heap space # 设置 JVM 最大可用内存为 1G # Xmx represents the maximum size of total heap space 
-Xms1g 
-Xmx1g

中文支持

在Kiabana的配置文件中修改,然后重启Kiabana即可:

代码语言:javascript复制
# Specifies locale to be used for all localizable strings, dates and number formats.
# Supported languages are the following: English - en , by default , Chinese - zh-CN .
i18n.locale: "zh-CN"

可视化操作

直接对索引操作:

文档的可视化操作

首先在左侧菜单进入Stack Management,然后选择索引模式新建一个索引模式,首次会进行引导

创建完成后,可以点击创建的索引进入详情页,进行操作,也可以直接在右上角创建索引模式继续创建索引

然后在左侧菜单选择Discover,就可以对文档进行可视化操作了

0 人点赞