页面加载中...

Elasticsearch简述与基本交互

| Elasticsearch | 0 条评论 | 454浏览

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交互一些基本且简单的命令,更多复杂且强大的命令可继续见后面的帖子。

发表评论

最新评论

    来第一个评论吧!