Menu Close

Elasticsearch 5.51 笔记 (1)

本文参考 ES全文指南翻译版,做出一些学习笔记,顺便修改了一些过时代码。以保证在ES5.51版可用。

Elasticsearch 建立在Lucene基础上的搜索引擎,Lucene 是当今最先进,最高效的全功能开源搜索引擎#框架。

特点:

  • 分布式实时文件存储.
  • 实时分析的分布式搜索引擎。
  • 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。

因为ES使用RESTful做接口,那么它不仅是跨平台的,而且也是跨语言的。

安装

可以在此页面安装最新版本的ES

如果你需要安装ELK,那么需要注意版本号,三个版本号必须得是一直的。
ELK就是Elasticsearch && logstash && kibana

运行

进入Elasticsearch目录,执行./bin/elasticsearch

执行上述命令,会在终端保持,如果想在后台运行,可以使用 ./bin/elasticsearch -d

RESTful交互方式可以使用终端自带的Curl,也可以使用postman,kibana的Dev Tools。

默认,开启的是本机9200端口,可以在浏览器输入 "http://localhost:9200/?pretty"

返回信息{

"name" : "e-w08f7",
"cluster_name" : "app",
"cluster_uuid" : "YfLUi2T0QTi36ECLRf3ggA",
"version" : {

"number" : "5.5.1",
"build_hash" : "19c13d0",
"build_date" : "2017-07-18T20:44:24.823Z",
"build_snapshot" : false,
"lucene_version" : "6.6.0"

},
"tagline" : "You Know, for Search"
}

API:

非java语言可以使用resultful风格向本机9200发送请求,例如查询集群总数。

GET _count?pretty 使用kibana的Dev Tools

curl -XGET 'http://localhost:9200/_count?pretty'  使用终端curl命令

demo

  1. 相应的 HTTP 请求方法 或者 变量 : GET, POST, PUT, HEAD 或者 DELETE。
  2. 集群中任意一个节点的访问协议、主机名以及端口。
  3. 请求的路径。
  4. 任意一个查询后再加上 ?pretty 就可以生成 更加美观 的JSON反馈,以增强可读性。
  5. 一个 JSON 编码的请求主体(如果需要的话)。

面向文档:

ES是面向文档型数据库,这意味着它存储的是整个对象或者 文档,它不但会存储它们,还会为他们建立索引.

ES 使用json做为文档序列化的格式.一个json对象可以理解为一个文档.

索引

这里的索引是一个动词,不是一个名词,区别与mysql的索引。
例子:
想象我们正在为一个名叫 megacorp 的公司的 HR 部门制作一个新的员工名单系统,这些名单应该可以满足实时协同工作,所以它应该可以满足以下要求:

  1. 数据可以包含多个值的标签、数字以及纯文本内容,
  2. 可以检索任何职员的所有数据。
  3. 允许结构化搜索。例如,查找30岁以上的员工。
  4. 允许简单的全文搜索以及相对复杂的短语搜索。
  5. 在返回的匹配文档中高亮关键字。
  6. 拥有数据统计与管理的后台。

结构化搜索可以理解为搜索一个类型,比如上文的30岁以上员工(where age > 30),比如只查找女性(where sex = 2),全文检索分两部分,一个是检索词,一个是文档,在存储为文档的时候,会将文档分词,拆分为一个一个的词语,检索词在检索时也会查分成一个一个词语,然后进行匹配。在查询的时候,可以通过参数获取高亮关键字。

关键字:索引、类型、文档

此处的索引相当于mysql的数据库,可以有多个索引,类型相当于数据表,文档就是一行一行数据,每个文档都代表一个员工.

操作流程:

  1. 为每一个员工的 文档 创建索引,每个 文档 都包含了一个员工的所有信息。
  2. 每个文档都会被标记为 employee 类型。
  3. 这种类型将存活在 megacorp 这个 索引 中。
  4. 这个索引将会存储在 Elasticsearch 的集群中

索引(数据库)为megacorp,类型(数据表)为employee,文档(列)就是每个员工的信息.

创建一个员工文档,并保存在megacorp索引中的employee类型下,不需要显示的创建,会在创建的过程中设定默认值。

PUT /megacorp/employee/1
{
    "first_name" : "John",
    "last_name" :  "Smith",
    "age" :        25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}

返回信息.
返回信息

此处可以看到,created的值为true,因为我已经创建过1的员工,如果再创建一次,created的值就会为false。

检索文档:

  1. 检索第一个员工,这里没有进行全文检索只是查询第一个员工,格式为GET /megacorp/employee/1

GET的HTTP操作方式,这里为读取,megacorp为索引名,employee为类型名,1为要查询的数据.
结果如下:

查询第一个员工

这里可以看到两个不同的命令,一个是PUT一个是GET,一个表示插入,一个表示读取,如果希望删除,则将GET修改为DELETE,如果希望查看是否存在,则使用HEAD,如果是更新数据,则还是使用PUT,数据格式同上。右侧可以看到我们想要的数据.

简易搜索

  1. 搜索整个类型下所有内容

GET /megacorp/employee/_search 表示搜索employee下的所有文档
搜索所有内容

右侧有几个关键词,total表示一共有多少个文档,hits表示所有文档,__index表示所属哪个索引,

__type表示为哪个类型.

  1. 搜索 姓氏包含Smith

GET /megacorp/employee/_search?q=last_name:Smith queryString方式.
不过query string方式有其局限性,比如说过滤器等等,可以采用更灵活、方便的 Query DSL方式.

    GET /megacorp/employee/_search
{
    "query" : {
        "match" : {
            "last_name" : "Smith"
        }
    }
}

这里使用了json作为查询条件,更为简洁干净。

更加复杂的搜索

查询条件为,last_name =Smith,并且年纪大于30。

GET megacorp/employee/_search
{
  "query": {
    "bool": {
      "must": { "match": {"last_name":"Fir"} },
      "filter": {
        "range": {
          "age": {
            "gte": 30
          }
        }
      }
    }
  }
}

以上demo工作在5.51版本。

全文搜索

搜索所有喜欢climbing(攀岩)的员工

GET megacorp/employee/_search
{
  "query": {
    "match": {
      "about": "climbing"  #这里测试时最好是多个词,因为es会进行拆分再进行匹配
    }
  }
}

精确匹配

返回精确匹配员工

GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    }
}

高亮关键字

增加highlight参数

GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    },
      "highlight": {
        "fields" : {
            "about" : {}
        }
    }
}

汇总、统计

员工中最受欢迎的兴趣是什么:

GET /megacorp/employee/_search
{
  "aggs": {
    "all_interests": {
      "terms": { "field": "interests" }
    }
  }
} 

在执行以上查询时会发生错误

Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead

5.x后对排序,聚合这些操作用单独的数据结构(fielddata)缓存到内存里了,需要单独开启.

执行以下操作

 PUT megacorp/_mapping/employee/
{
  "properties": {
    "interests": {
      "type":     "text",
      "fielddata": true
    }
  }
}

返回结果

上图右侧展示了,喜欢音乐的有4个,喜欢运动的有3个等等。

查找姓smith的兴趣汇总

GET /megacorp/employee/_search
{
  "query": {
    "match": {
      "last_name": "smith"
    }
  },
  "aggs": {
    "all_interests": {
      "terms": { "field": "interests" }
    }
  }
}

只需要加上刚才的query参数.

每个兴趣下的平均年龄

GET /megacorp/employee/_search
{
  "query": {
    "match": {
      "last_name": "smith"
    }
  },
  "aggs": {
    "all_interests": {
      "terms": { "field": "interests" },
      "aggs": {
        "age_avg": {
          "avg": {
            "field": "age"
          }
        }
      }
    }
  }
}

只需要在aggs下的terms后面增加aggs参数,aggs里的age_avg可以自定义。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注