Preface
Elasticsearch(以下简称Es或者es)官方文档: https://www.elastic.co/guide
Es部署安装:https://www.elastic.co/guide/cn/elasticsearch/guide/current/running-elasticsearch.html
Es简述
Elasticsearch 是一个分布式、可扩展、实时的搜索与数据分析引擎。 它能从项目一开始就赋予你的数据以搜索、分析和探索的能力,这是通常没有预料到的。 它存在还因为原始数据如果只是躺在磁盘里面根本就毫无用处。
Elasticsearch 是 面向文档 的,意味着它存储整个对象或 文档。Elasticsearch 不仅存储文档,而且 索引 每个文档的内容使之可以被检索。在 Elasticsearch 中,你 对文档进行索引、检索、排序和过滤--而不是对行列数据。这是一种完全不同的思考数据的方式,也是 Elasticsearch 能支持复杂全文检索的原因。
摘录自官方文档
可见,Es是分布式的,也就是集群多节点式的,进而能够保证你的数据能够在每个节点上都能找到。数据既然是保存在es集群的节点上,那么肯定具有某种格式,正如同保存在数据库里面的数据都是二维的表格式的。
在需要获取es上的数据前,可能需要先了解一下es的一些相关术语:
文档
保存在es种的数据称之为文档。如同在Java种描述某个自然实体,我们称之为对象。无论是es的文档还是Java的对象,都是存储着某个实体,es的文档其数据格式为json格式。
比如:
User user = new User();
user.setName("zhangsan");
user.setAge(19);
user.setPhone("10086123");
等价于es的Json文档:
{
"name":"zhangsan",
"age":19,
"phone":"10086123"
}
但是,一个文档不仅仅包括它的数据,还包含它的一些元数据,及文档的有关信息。三个必须的元数据为:
- _index 索引 : 表示文档在哪里存放
- _type 类型 : 表示文档的对象类别
- _id : 表示文档的唯一标识
索引
我们把实体对象存储在es中,叫做文档。那么该条数据存在Es的行为就称之为索引,索引也就是确定我们要存储的文档时放在什么地方。
所以,一个索引应该是具有某些共同特性的文档的集合。比如对班里的学生进行分组,可以按性别作为索引进行分,也可以按年龄作为索引来分。。
实际上,在 Elasticsearch 中,我们的数据是被存储和索引在 分片 中,而一个索引仅仅是逻辑上的命名空间, 这个命名空间由一个或者多个分片组合在一起。 然而,这是一个内部细节,我们的应用程序根本不应该关心分片,对于应用程序而言,只需知道文档位于一个 索引 内。 Elasticsearch 会处理所有的细节。
From 官方文档
类型
类型可以认为是索引的子分区。因为数据可能在索引中只是松散的组合在一起,还需要对这些数据再进行一些划分。
tips: 在7.0版本以后,类型被删除了,不再用了。
倒排索引
倒排索引(Inverted Index)也叫反向索引,有反向索引必有正向索引。通俗地来讲,正向索引是通过key找value,反向索引则是通过value找key。
前面知道,es的文档是json格式的,相当于我们知道了某个对象了,就能知道对对象的一系列属性。但有时候,我们指定某些条件(对象属性),需要知道哪些对象符合要求。
举个例子:需要买个手机,市场上有很多牌子的手机,配置也不尽相同:
华为100(6G内存,64G存储,8核处理器,全面屏,2000w像素,¥3999)
小米66(6G内存,64G存储,8核处理器,刘海屏屏,1200w像素,¥2998)
oppo80(4G内存,128G存储,4核处理器,全面屏,3200w像素,¥3599)
如果不是对某种手机情有独钟的话,一般就是自己认为的配置来挑选手机了,我们根据配置来列手机:
配置 | 华为100 | 小米66 | oppo80 |
---|---|---|---|
6G内存 | √ | √ | |
128G存储 | √ | ||
8核处理器 | √ | √ | |
2000w像素 | √ | √ | |
全面屏 | √ | √ | |
RMB>3000 | √ | √ |
如上,这下子就直接根据自定义的配置来挑选适合的手机了。比如预算有限,性能也不差的,唉,那么小米66可能是你最好的选择。
像这种通过内容来确定文档的数据结构就称之为倒排索引。不过Es中的倒排索引结构较为复杂,不仅支持精确、模糊匹配,还能支持相似性的匹配。可见es的分析与分析器
与Es交互
与Es交互两种方式,一种是直接curl Es的rest风格的url,另一种是通过java代码调用es的API方式。这里采用第一种。
部署安装完数据后,先put一些数据
一些约定:
我本地的es 地址是http://172.22.0.153:9200
那么我会将curl 简写,如:
curl -X GET http://172.22.0.153:9200/demo/test
curl -X POST http://http://172.22.0.153:9200/demo/test -d {"k1":"v1","k2":"v2"}
简写成
GET /demo/test
POST /demo/test {"k1":"v1","k2":"v2"}
对于带参数的,我会将形如这种:
curl http://172.22.0.153:9200/esb-inparam-2019-04-16/doc/_search -H 'Content-Type: application/json' -d '{"query":{"match":{"head":"sQUByPhoneNo"}}}'
简写成
GET /esb-inparam-2019-04-16/doc/_search
{
"query": {
"match": {
"head": "sQUByPhoneNo"
}
}
}
空搜索
首先,我们直接通过如下命令看es是否安装成功:
GET /
结果如下:
{
"name" : "estest",
"cluster_name" : "stqtest",
"cluster_uuid" : "mQRmNfz9T0KwlLlrzcfnDA",
"version" : {
"number" : "6.1.1",
"build_hash" : "bd92e7f",
"build_date" : "2017-12-17T20:23:25.338Z",
"build_snapshot" : false,
"lucene_version" : "7.1.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
说明es安装部署没得问题了。
查询所有的文档:
GET /_search
#或者加个后缀 ?pretty 能够格式化输出
# GET /_search?pretty
结果如下,
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 20,
"successful" : 20,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 571381,
"max_score" : 1.0,
"hits" : [
{
"_index" : "esb-inparam-2019-04-16",
"_type" : "doc",
"_id" : "OV67JWoBTmrv2vNCZvGM",
"_score" : 1.0,
"_source" : {
"source" : "/hadoop/inParam.log",
"time" : "20190416 05:32:33.779",
"clientip" : "10.112.101.42",
"head" : "sTSNPubSnd2",
"id" : "0",
"tags" : [
"_dissectfailure"
],
"fields" : {
"host" : "eshost",
"_clientip" : "172.22.0.153"
},
"request" : "POST",
"@timestamp" : "2019-04-16T05:32:33.779Z",
"prospector" : {
"type" : "log"
},
"type" : "inparam",
"json_data" : "{ "ROOT": { "HEADER": { "ROUTING": { "ROUTE_KEY": "14", "ROUTE_VALUE": "aadmin" }, "POOL_ID": "11", "CHANNEL_ID": "40", "USERNAME": "crmtux1", "PASSWORD": "247wJ7XO63jrspEjCNQdlg==" }, "BODY": { "BIP_CODE": "P9999999", "TRANS_CODE": "S9999999", "LOGIN_NO": "yjboss", "ORG_CODE": "", "OP_NOTE": "???BBOSS???", "OPR_INFO": { "FUNC_CODE": "F0001740", "LOGIN_NO": "yjboss", "GROUP_ID": "", "OP_NOTE": "???BBOSS???" }, "BUSI_INFO": { "BUSINESS_TYPE": "1", "CUSTOMER_PHONE": "13684470235", "MEM_TYPE": "1", "BIZ_VERSION": "1.0.0" } } } }"
}
},
{
先看hits里面的,total表示总共匹配了571381条数据,hits里面就是匹配的数据,只不过默认只会展示前10条数据。_source里面就是匹配的文档。
轻量搜索
之前说过,通过索引_index、类型_type、_id可唯一标识一条记录。所以我们也可以直接来找某个文档:
GET /esb-inparam-2019-04-16/doc/OV67JWoBTmrv2vNCZvGM
如果不知到id,可以先用_index和_type如下命令搜索除所有的文档,如下:
GET /esb-inparam-2019-04-16/doc/_search
可能我们只晓得该文档里面的某个属性,如服务名,通过参数来查找文档,如下:
GET /esb-inparam-2019-04-16/doc/_search?q=head:sQUByPhoneNo
如果hai'de还得继续筛选,比如查找服务名为sQUByPhoneNo并且clientIp为10.113.181.205的文档,实际上的查询参数是这样的,
+Bhead:sQUByPhoneNo +clientip:10.113.181.205
+前缀表示必须与查询条件匹配,类似地, -前缀表示一定不与查询条件匹配。
转义到url的查询就是
GET /esb-inparam-2019-04-16/doc/_search?pretty&q=%2Bhead%3AsQUByPhoneNo+%2Bclientip%3A10.113.181.205
如上,这样的可读性特别差,向这种轻量搜索也就只适合即时的简单查询。更复杂的查询还可以使用es的表达式查询
表达式搜索
Elasticsearch 提供一个丰富灵活的查询语言叫做 查询表达式 , 它支持构建更加复杂和健壮的查询。这个被称之为领域特定语言 (DSL),需要我们指定一个查询的json体。
如之前的那个知道服务名来查询文档,我们可以写为:
GET /esb-inparam-2019-04-16/doc/_search
{
"query": {
"match": {
"head": "sQUByPhoneNo"
}
}
}
tip:在使用curl命令时,需要指定下参数类型,上述的原命令如下:
curl http://172.22.0.153:9200/esb-inparam-2019-04-16/doc/_search?pretty -H 'Content-Type: application/json' -d '{"query":{"match":{"head":"sQUByPhoneNo"}}}'
多参数的查询,使用match匹配:
GET /esb-inparam-2019-04-16/doc/_search
{
"query": {
"bool": {
"must": {
"match": {
"head": "sQUByPhoneNo"
}
},
"filter": {
"match": {
"clientip": "10.113.181.205"
}
}
}
}
}
或者并不需要某个值,而是匹配范围,可以使用range。如下,查询id大于0的:
GET /esb-inparam-2019-04-16/doc/_search
{
"query": {
"range": {
"id": {
"gt": "0"
}
}
}
}
以上是与es交互一些基本且简单的命令,更多复杂且强大的命令可继续见后面的帖子。
发表评论