1、ElasticSearch介绍

1.1 ES的根底介绍

1.1.1 为什么有ES

关于全文检索,有许多的东西能够运用,如Apache Lucene,它是一个全文搜索引擎库,但是在运用Apache Lucene时,其复杂性远远超出了一个正常的程序员所具有的知识。为了能够解决这个问题,因而,根据Apache Lucene,运用Java言语编写出了ElasticSearch,其隐藏了Apache Lucene底层的复杂性,开发了一套简略的RESTful API。

1.1.2 根底概念

① Index索引

index在elasticsearch中有两个意义,一个是作为新增数据,一个是作为索引。

② Type类型

在一个index索引中,能够界说一个或多个类型。

③ Document文档

保存在某个索引下的某个类型的一条数据,这条数据是以JSON的格局进行寄存。 上述的这三个概念,能够用MySQL进行类比:

ES概念 MySQL概念
index database
type table
document 记载

1.1.3 关于MySQL能够进行查找,为什么还要运用ES

关于MySQL的查找,其底层能够运用equal进行全值查找或者是like进行模糊查找,而这个操作是比较慢的,它会逐一去判别每条数据是否匹配,假设匹配了才会作为查找的成果。而MySQL在刺进数据的过程中,会依照次序,一条数据一条数据的刺进,哪怕有几条数据的某些部分值是差不多,也会依照次序进行排放。 而关于ES而言,它底层会在刺进时,会保护一个倒排索引表,在这个倒排索引表中,会有两个字段,一个字段是对应的词,一个字段是包含该词的一切记载。而这些词,在刺进数据时,会对数据进行拆分,将其拆分为若干个词并记载进这个倒排索引表中。 举例: 假设咱们现在要刺进的数据如下:

1-红海举动
2-探究红海举动
3-红海特别举动
4-红海记载篇
5-奸细红海特别探究

那么,ES会将每条记载进行拆分,如红海举动,能够将其拆分为红海举动,也能够将其拆分为四个词,然后将其存入倒排索引表中,这儿咱们运用第一种方法。

记载
红海 1
举动 1

上述的表格是在刺进第一条数据之后所形成的倒排索引表 接着咱们刺进第二条数据,会将其拆分为探究红海举动三个词 于是此刻的倒排索引表如下

记载
红海 1,2
举动 1,2
探究 2

后面的三条数据也是依照这样的操作逐一区分并存入倒排索引表中

记载
红海 1,2,3,4,5
举动 1,2,3
探究 2,5
特别 3,5
记载篇 4
奸细 5

这便是终究生成的倒排索引表,而假设咱们要进行查找时,假设咱们要查找 红海特别举动 那么,相同的,在查找时,也会将这个词拆分为多个词,拿着拆分出来的词去倒排索引表中去查找,在倒排索引表假设有某条数据的词等于拆分出来的一个或多个词,那么就将该词对应的记载纳入成果会集。 此刻将 红海特别举动拆分为三个词,红海特别举动。 于是乎,就去查找红海,发现有该词,且记载为1,2,3,4,5,于是这5条记载就作为成果,接着去查找特别,发现也有,记载为3,5,此刻发现成果会集有这些于是不重复增加,相同的关于举动也是,因而,终究找到的成果集为1,2,3,4,5。然后将这些数据进行显现。

1.2 ES的装置以及装备发动

1.2.1 ES的装置

docker pull elasticsearch:7.4.2

1.2.2 ES的装备及发动

创建出两个文件用于挂载ES内部的文件内容

mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data

创建出对应的装备文件,并在装备文件中增加信息

echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml

镜像的运转以及相应文件的挂载

docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e  "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx128m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v  /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2 

修正对应的文件让一切人都能够拜访ES

chmod -R 777 /mydata/elasticsearch

发动ES

docker start elas

能够设置开启虚拟机时默认发动ES

docker update elasticsearch --restart=always

终究在浏览器中输入对应的虚拟机地址以及端口号,如192.168.78.10:9200即可获取如下的界面,这样子就阐明ES现已装置成功

{
  "name" : "72ed6c8d6e0b",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "_q-EIRuaQbOvJIfFkgbcfg",
  "version" : {
    "number" : "7.4.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "2f90bbf7b93631e52bafb59b3b049cb44ec25e96",
    "build_date" : "2019-10-28T20:40:44.881551Z",
    "build_snapshot" : false,
    "lucene_version" : "8.2.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

2、Kibana介绍

2.1 Kibana介绍

kibana是一个可视化界面,能够用于检查ES中的数据 kibana和ES的关系类似于Mysql和Sqlyog的关系,一个用于保存数据,一个用于运用图形化的界面检查当时保存的一切数据内容

2.2 Kibana的装置

kibana的版别要与ES对应,如,这儿咱们运用的ES版别是7.4.2,那么咱们的Kibana的版别也要7.4.2才能够。

docker pull kibana:7.4.2

接着发动咱们的kibana

docker run --name kibana \
-e ELASTICSEARCH_HOSTS=http://ip:9200 \
-p 5601:5601 \
-d kibana:7.4.2

留意,前面的http://ip需求填写自己虚拟机的ip地址 咱们能够在本地主机中测验一下当时是否装置成功,在浏览器中输入ip:5601,假设能弹出如下的界面即阐明现已成功装置了

学习谷粒商城之ElasticSearch入门使用

2.3 Kibana的相关操作

2.3.1 查询节点的状况_cat

① 检查一切节点的状况

http://{ip}:9200/_cat/nodes

127.0.0.1 55 99 9 0.58 0.38 0.30 dilm * 72ed6c8d6e0b
② 查询ES的健康状况

http://{ip}:9200/_cat/health

1687004907 12:28:27 elasticsearch green 1 1 4 4 0 0 1 0 - 80.0%
③ 检查主节点的状况

http://{ip}:9200/_cat/master

HzW2sAa0QTO9Vt1VZTuuFg 127.0.0.1 127.0.0.1 72ed6c8d6e0b
④ 检查一切索引的状况

http://{ip}:9200/_cat/`indices`

green open .kibana_task_manager_1   1X5FwZ7zT1ODNuOo7c96tg 1 0 2 0 38.2kb 38.2kb
green open .apm-agent-configuration PUnTh1VuQSKEQ3h37K4XOA 1 0 0 0   283b   283b
green open .kibana_1                yoL51QcrQO-xtZ51WqsOfA 1 0 7 0 25.2kb 25.2kb

2.3.2 新增文档

下面的操作运用postman软件进行模仿,后续再转为kibana自带的

① put恳求

第一次发送put恳求时http:192.168.78.10/customer/external/1 附上的json数据为

{
	"name": "John Doe"
}

回来的数据如下

{
"_index":"customer",
"_type":"external",
"_id":"1",
"_version":1,
"result":"created",
"_shards":{
"total":2,
"successful":1,
"failed":0
},
"_seq_no":0,
"_primary_term":1
}

接着咱们再发送一次当时恳求

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 2,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 1,
    "_primary_term": 1
}

能够发现,关于_id而言,其值没有发生变化,这个id是唯一标识这条数据的。 而咱们能够调查_version和result两个字段的值,第一次的时分是1和created,第2次的时分就变成了2和updated。阐明_version字段是动态更新的,每次修正该条数据的值都会变动一次,而假设自身有这条数据,那么就会是修正的状况,假设自身没有这条数据,那么就会是新增的状况。

② post恳求

第一次发送post恳求时http:192.168.78.10/customer/external 附上的json数据为

{
	"name": "John Doe"
}

回来的数据如下:

{
    "_index": "customer",
    "_type": "external",
    "_id": "VrVZyYgBfKt3Fbn5XnLP",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 2,
    "_primary_term": 1
}

而咱们再次发送相同的恳求时

{
    "_index": "customer",
    "_type": "external",
    "_id": "V7VayYgBfKt3Fbn5WHLl",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 3,
    "_primary_term": 1
}

能够发现,这两次回来的数据,从id上来看就不相同了。

2.3.3 查询文档

get恳求用于查询文档,发送的恳求途径与put的恳求途径是相同的 回来的数据如下

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 2,
    "_seq_no": 1,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "John Doe"
    }
}

2.3.4 更新文档

① post带_update

http://{ip}:9200/customer/external/1/_update 恳求体所带着的数据为:

{
"doc":{
"name":"John"
}
}

回来的数据为:

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 3,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 4,
    "_primary_term": 1
}

第2次发送相同恳求且恳求体中带着相同数据的时分,回来的数据为:

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 5,
    "result": "noop",
    "_shards": {
        "total": 0,
        "successful": 0,
        "failed": 0
    },
    "_seq_no": 6,
    "_primary_term": 1
}

能够看到,对比上述两次操作,第一次操作的成果为updated,第2次操作的成果为noop,也便是说,当发送数据要去更新文档时,会先去检测所带着的数据是否相同,假设相同的话,则不操作既noop,假设不同的话才会去进行更新操作即updated。

② post不带_update

http://{ip}:9200/customer/external/1 恳求体所带着的数据为:

{
"name":"John"
}

回来的数据为:

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 5,
    "result": "updated",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 6,
    "_primary_term": 1
}

这儿的post即是前面新增文档时的post

③ put

这儿相同也是

④ put和post恳求的对比
Ⅰ、差异一:恳求途径的不同

关于put和post恳求的差异在于,put恳求时需求带着当时是第几条数据,而post则不带着当时是第几条数据 如

put: http:192.168.78.10/customer/external/1
post: http:192.168.78.10/customer/external
Ⅱ、差异二:新建仍是修正

put恳求会先去判别当时所带参数的数据是否存在,假设存在,那么会进行修正操作,假设不存则新增该条数据 而post恳求则是不管有没有都是新增操作

Ⅲ、差异三:新建数据的id

早年面的比如能够看到,假设是put恳求的话,终究生成的数据id会是带着参数的值 而假设是post恳求的话,终究生成的数据id会是一个随机数

Ⅳ、更新规模

post恳求是会将对应增加的数据进行修正 当时数据

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 13,
    "_seq_no": 14,
    "_primary_term": 1,
    "found": true,
    "_source": {
		"name": "John",
        "age": 20
    }
}

post恳求带着了_update参数时,此刻带着的恳求体的数据如下:

{
"doc":{
"age":22
}
}

此刻从头查询文档

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 13,
    "_seq_no": 14,
    "_primary_term": 1,
    "found": true,
    "_source": {
		"name": "John",
        "age": 22
    }
}

假设是带着了_update恳求参数,那么,只会修正恳求参数中不同的值,关于恳求参数中没有带着的字段的,是不进行操作的。 post恳求不带着_update参数时,此刻从头更新,恳求体带着的数据如下:

{
"age":20
}

此刻从头查询文档

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 13,
    "_seq_no": 14,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "age": 20
    }
}

能够发现,此刻的name字段现已消失了,只要age这一个字段。 此刻恢复数据,咱们来测验一下put

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 13,
    "_seq_no": 14,
    "_primary_term": 1,
    "found": true,
    "_source": {
		"name": "John",
        "age": 22
    }
}

put恳求体带着的数据为:

{
"age":20
}

此刻从头查询,其成果为

{
    "_index": "customer",
    "_type": "external",
    "_id": "1",
    "_version": 18,
    "_seq_no": 19,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "age": 20
    }
}

能够发现,此刻的put与之前的post不带_update参数时是相同的。 所以,put和不带_update参数的post相同都是全量更新,其底层会先把这条数据删掉,然后从头增加一条新的数据。 而带了_update参数的post是增量更新,底层是会对恳求体的参数中所带着的同名的字段的值进行修正,再增加原本数据中没有的字段。

2.3.5 删去文档

前面咱们都是运用的postman软件用来履行的这些操作,接下来咱们运用Kibana自带的东西来运用。 Kibana自带的东西如下图所示打开

学习谷粒商城之ElasticSearch入门使用
点击后能够进入如下的界面:

学习谷粒商城之ElasticSearch入门使用
整个界面分为两部分,左面为要履行的恳求,右边为履行的成果。 每个恳求都会有一个播放按钮,它会履行当时的恳求,会以每个action作为分割,不会去履行其他的action

① 删去单个文档

运用DELETE /customer/external/1

{
  "_index" : "customer",
  "_type" : "external",
  "_id" : "1",
  "_version" : 19,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 20,
  "_primary_term" : 1
}

此刻删去再次查询时回来的数据信息为:

{
  "_index" : "customer",
  "_type" : "external",
  "_id" : "1",
  "found" : false
}

能够发现,found字段的值为false,阐明当时并没有找到id为1的文档。

② 删去整个索引

运用DELETE /customer 此刻回来的数据为:

{
  "acknowledged" : true
}

此刻从头查找,会报如下的错误信息

{
  "error" : {
    "root_cause" : [
      {
        "type" : "index_not_found_exception",
        "reason" : "no such index [customer]",
        "resource.type" : "index_expression",
        "resource.id" : "customer",
        "index_uuid" : "_na_",
        "index" : "customer"
      }
    ],
    "type" : "index_not_found_exception",
    "reason" : "no such index [customer]",
    "resource.type" : "index_expression",
    "resource.id" : "customer",
    "index_uuid" : "_na_",
    "index" : "customer"
  },
  "status" : 404
}

此刻的状况为404,阐明未找到当时的索引 咱们能够删去单条文档和整个索引,但是不能删去中心那个

2.3.6 批量Api

批量操作时,不同于mysql数据库中的某条履行犯错悉数回滚的操作,这儿每一条操作的运转是独立的,互相互不干扰,上一条数据的成果不会影响下一条数据的履行。 批量api能够进行的操作是:indexcreatedeleteupdate 其间index和create是增加操作,能够增加文档,需求在后面增加一些参数 delete是删去操作,能够删去一个文档,不要求在后面增加 update是修正操作,能够修正一个文档,要求在下一行中指定部分 doc、更新刺进(upsert)、脚本及其选项。

其语法格局为:

{"action": {metadata}}
{requestbody }
{"action": {metadata}}
{requestbody }

其间的action便是对应于前面四种操作,metadata便是需求进行此操作的某个索引下的某个类型下的某个文档,都需求唯一标识。 而下面的requestbody便是咱们要运用到的数据。 如前面咱们运用的是Postman用来履行的一些操作中,咱们在恳求体中增加的数据,便是这儿的requestbody。 下面运用两个案例来体会一下运用批量Api进行操作

① 批量增加数据

咱们履行的句子为:

POST /customer/external/_bulk
{"index":{"_id":"1"}}
{"name":"John Doe"}
{"index":{"_id":"2"}}
{"name":"Jane Doe"}

此刻回来的数据为:

{
  // 履行本次操作所花费的时刻,单位是ms
  "took" : 606, 
   // 有无犯错,这儿值为false,阐明悉数都成功了,假设有一个没成功则为true
  "errors" : false, 
  // 每个操作所履行的成果
  "items" : [
    {
     // 履行的是index操作
      "index" : {
        // 操作的索引名
        "_index" : "customer",
        // 操作的类型名
        "_type" : "external",
        // 操作的文档id
        "_id" : "1",
        // 该文档对应的版别号,默认值为1,每次对其进行修正时都会加1
        "_version" : 1,
        // 本次操作履行的成果是created表明为新建,假设是修正则为updated
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        // 并发控制字段,每次更新就会加1,用来做乐观锁
        "_seq_no" : 0,
        // 同上,主分片从头分配,如重启就会变化
        "_primary_term" : 1,
        // 当时履行的成果的状况码
        "status" : 201
      }
    },
    {
      "index" : {
        "_index" : "customer",
        "_type" : "external",
        "_id" : "2",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 1,
        "_primary_term" : 1,
        "status" : 201
      }
    }
  ]
}
② 批量履行不同的操作

此刻的履行句子为:

POST /_bulk
{"delete": {"_index": "website", "_type": "blog", "_id": "123"}}
{"create": {"_index": "website", "_type": "blog", "_id": "123"}}
{"title": "My first blog post"}
{"index": {"_index": "website", "_type": "blog"}}
{"title": "My second blog post"}
{"update": {"_index": "website", "_type": "blog", "_id": "123"}}
{"doc": {"title": "My updated blog post"}}

回来的数据信息为:

{
  "took" : 3373,
  "errors" : true,
  "items" : [
    {
      "delete" : {
        "_index" : "website",
        "_type" : "blog",
        "_id" : "123",
        "_version" : 2,
        "result" : "not_found",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 1,
        "_primary_term" : 1,
        "status" : 404
      }
    },
    {
      "create" : {
        "_index" : "website",
        "_type" : "blog",
        "_id" : "123",
        "status" : 409,
        "error" : {
          "type" : "version_conflict_engine_exception",
          "reason" : "[123]: version conflict, document already exists (current version [4])",
          "index_uuid" : "H_4_xzfKR4GnkIEcGXdovQ",
          "shard" : "0",
          "index" : "website"
        }
      }
    },
    {
      "index" : {
        "_index" : "website",
        "_type" : "blog",
        "_id" : "WbW2yYgBfKt3Fbn5W3Kx",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 5,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "update" : {
        "_index" : "website",
        "_type" : "blog",
        "_id" : "123",
        "_version" : 4,
        "result" : "noop",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 4,
        "_primary_term" : 1,
        "status" : 200
      }
    }
  ]
}

2.3.8 增加测验数据

测验数据:es测验数据.json 坐看云起时/common_content – Gitee.com 将这些测验数据存进/bank/account/_bulk中 此刻从头检查当时的一切索引

yellow open website                  H_4_xzfKR4GnkIEcGXdovQ 1 1    3 3   8.8kb   8.8kb
yellow open bank                     UPeWuTxBRv61vW_WGjoULg 1 1 1000 0 422.1kb 422.1kb
green  open .kibana_task_manager_1   1X5FwZ7zT1ODNuOo7c96tg 1 0    2 0  38.2kb  38.2kb
green  open .apm-agent-configuration PUnTh1VuQSKEQ3h37K4XOA 1 0    0 0    283b    283b
green  open .kibana_1                yoL51QcrQO-xtZ51WqsOfA 1 0    8 0  28.6kb  28.6kb
yellow open customer                 PL1lo4qzQtGiT4Y4K4OdbA 1 1    2 0   3.5kb   3.5kb

学习谷粒商城时,学到了ElasticSearch技术,因而记载下学习过程中的一些笔记以及一些弥补。将我做的笔记分享出来,期望能够帮助到其他人,假设有缺乏的地方也期望大家能指出,谢谢!!