ElasticSearch基础

一. Elasticsearch简介

ES是一个基于Lucene的搜索服务器,它提供一个分布式多用户能力的全文搜索引擎,基于RESTful web接口,ES是使用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能达到实时搜索、稳定、可靠、快速、安装使用方便。

Elasticsearch是一个分布式、可扩展、实时的搜索与数据分析引擎。

Elasticsearch被用作全文搜索、结构化搜索、分析以及这三个功能的组合。

Elasticsearch是一个开源的搜索引擎,建立在一个全文搜索引擎库Apache Lucene基础之上。

Elasticsearch使用Java编写内部使用Lucene做索引和搜索,其目的是使全文索引变得简单,通过隐藏Lucene的复杂性,取而代之的提供一套简单一致的RESTful API。

归纳总结

  • 一个分布式的实时文档存储,每个字段可被索引和搜索。
  • 一个分布式实时分析的搜索引擎
  • 能胜任上百个服务节点的扩展,并支持PB级别的结构化或非结构化数据。

二. Elasticsearch安装

操作系统:Ubuntu 16.04 LTS

1. 安装java

# 查看java版本
$  java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

# java编译器
$ javac

Elasticsearch recommends Oracle JDK version 1.8.0_73, but the native Ubuntu OpenJDK native package for the JRE works as well.

推荐安装JDK8

$ sudo add-apt-repository -y ppa:webupd8team/java

$ sudo apt-get update

$ sudo apt-get -y install oracle-java8-installer

$ java -version

2. 安装Elasticsearch

建议采用源码包安装,使用 sudo apt-get install elasticsearch 出现下列错误。

# 安装elasticsearch

$ sudo apt-get update 

$ sudo apt-get install elasticsearch


# 安装curl

$ sudo apt-get install curl

$ curl -version
# 查看系统类型

$ ps -p 1
# systemd下启动、关闭、重启elasticsearch

$ sudo systemctl start elasticsearch.service

$ sudo systemctl stop elasticsearch.service

$ sudo systemctl restart elasticsearch.service

$ sudo systemctl status elasticsearch.service
# 查看elasticsearch日志
$ ll /var/log/elasticsearch/

#查看日志
$ sudo journalctl -f

$ sudo journalctl --unit=elasticsearch
## 测试elasticsearch
$ curl 'http://localhost:9200/?pretty'

出现问题

jc@jcos:~$ curl 'http://127.0.0.1:9200/?pretty'
curl: (7) Failed to connect to 127.0.0.1 port 9200: 拒绝连接


root@jcos:~# curl -XGET 'localhost:9200'
curl: (7) Failed to connect to 127.0.0.1 port 9200: 拒绝连接

# 查看9200端口
root@jcos:~# netstat -tulpn | grep 9200

解决方案参照:
https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-elasticsearch-on-ubuntu-14-04

3. 源码包安装

下载最新版本的 elasticsearch

目前最新版本

https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.3.deb

# wget 下载
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.3.deb

# 解压安装deb
$ sudo dpkg -i elasticsearch-5.4.3.deb

# 安装后elasticsearch位于
$ cd /usr/share/elasticsearch/

# 开启服务
$ system.md start elasticsearch.service

测试:启动elasticsearch节点
$ curl -X GET 'http://localhost"9200'
{
  "name" : "orc_HnJ",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "m9RkECrAToWEVAjEdpidMw",
  "version" : {
    "number" : "5.4.3",
    "build_hash" : "eed30a8",
    "build_date" : "2017-06-22T00:34:03.743Z",
    "build_snapshot" : false,
    "lucene_version" : "6.5.1"
  },
  "tagline" : "You Know, for Search"
}

将ES加入到系统启动文件并启动ES服务

# 加入开启自启动
$ sudo update-rc.d elasticsearch default 95 1

# 启动服务
$ sudo /etc/init.d/elasticsearch start

# CURL测试
$ curl -X GET "http://localhost:9200"

单个节点可作为一个运行中Elasticsearch实例,而一个集群是一组拥有相同cluster.name的节点,他们能一起工作并共享数据,还提供容错和可伸缩性。可在/etc/elasticsearch.yml配置文件中修改cluster.name,该节点会在节点启动时加载。

3. 安装Kibana

kibana是一个用于Elasticsearch分析和查询的仪表盘,它最吸引人的应该是NB的图标和表现能力。

下载安装 kibana
https://www.elastic.co/downloads/kibana

Kibana服务

# 启动kibana
$ systemctl start kibana.service

# 关闭kibana
$ systemctl stop kibana.service

# 查看kibana状态
$ systemctl status kibana.service

# 重启 kibana
$ systemctl restart kibana.service

# 使用deb安装kibana位于
$ cd /usr/share/kibana/

地址栏输入 localhost:5601

4. 安装Sense

Sense是一个Kibana应用,它提供交互式控制台,通过浏览器直接向Elasticsearch提交请求。

https://github.com/elastic/sense

HEADS UP: This repo is deprecated. Sense is now included as Console in Kibana 5.0. File issues over at elastic/kibana

目前sense已经集成到Kibana5中,访问 http://localhost:5601 打开左侧菜单栏 Dev Tools 此处就是 sense

例如:计算集群中文档的数据量
在Dev Tools中输入

GET /_count
{
  “query":{
    "match_all":{}
  }
}

三. 和Elasticsearch交互

和Elasticsearch交互取决于你是否使用java,ES为Java用户提供两种内置客户端:

  • 节点客户端(node cilent)
    节点客户端作为一个非数据节点加入到本地集群中,换句话说它本身不保存任何数据,但是它知道数据在集群中那个节点中,并可把请求转发到正确的节点。

  • 传输客户端(transport client)
    轻量级的传输客户端可将请求发送到远程集群,它本身不加入集群,但可将请求转发到集群中的一个节点上。

两个java客户端都是通过9300端口并使用本地ES传输协议和集群交互,集群中的节点通过端口9300彼此通信。若端口没有打开,节点将无法形成一个集群。

基于HTTP协议,以JSON为数据交换格式的RESTful API
其他所有语言都可使用RESTful API,通过9200端口与ES通信,可使用你喜欢的web客户端,设置可通过curl命令与ES通信。

四. 面向文档

ES是面向文档的,意味着可存储整个对象文档,而且索引每个文档的内容使之可被检索。在ES中,对文档进行索引、检索、排序、过滤而不是对行列数据,这种不同的思考数据的方式,也是 ES 能支持复杂全文检索的原因。Elasticsearch 使用 Javascript Object Notation 或 JSON 作为文档的序列化格式。

案例:创建一个雇员目录的业务需求

  • 支持包含多值标签、数值、全文本数据
  • 检索任一雇员的完整信息
  • 允许结构化搜索,比如查询30岁以上的员工
  • 允许简单的全文搜索以及较复杂的短语搜索
  • 支持在匹配文档内容中高亮显示搜索片段
  • 支持基于数据创建和管理分析仪表盘

1. 索引雇员文档

以雇员文档形式存储,一个文档代表一个雇员。存储数据到 Elasticsearch 的行为叫做索引,但在索引一个文档之前,需确定文档存储位置。

一个 Elasticsearch 集群可包含多个索引,相应每个索引可包含多个类型,不同类型存储多个文档,每个文档有多个属性。

一个索引类似于关系数据库中一个数据库,一个存储关系文档的地方,索引一个文档就是存储一个文档到一个索引(名称)中以便被检索和查询。关系数据库通过增加一个索引到指定列以提升数据检索速度。elasticsearch使用一个叫做倒序索引的结构来达到相同目的。
默认一个文档中每个属性都是被索引的和可搜索的,一个没有倒序索引的属性是不能被搜索的。

对于雇员目录将做如下操作

  • 每个雇员索引一个文档,包含雇员的所有信息。
  • 每个文档都将是 employee 类型
  • employee 类型位于 megacorp内
  • 该索引保存在Elasticsearch集群中

Dev Tool输入

// 创建一个索引或执行每个属性的数据类型 : megacorp 索引名称 / employee 类型名称 / 1 特定雇员编号
// 请求体,JSON文档中包含员工详细信息
PUT /megacorp/employee/1
{
  "firstname":"John",
  "lastname":"smith",
  "age":25,
  "introduce":"i love to go rock climbing",
  "interests": ["sports", "music"]
}

返回结果

{
  "_index": "megacorp",
  "_type": "employee",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

继续创建索引

PUT /megacorp/employee/2
{
  "firstname":"Jane",
  "lastname":"Smith",
  "age":32,
  "introduce":"i like to collect rock albums",
  "interests":["music"]
}

PUT /megacorp/employee/3
{
  "firstname":"Douglas",
  "lastname":"Fir",
  "age":35,
  "introduce":"i like to build cabinets",
  "interests":["forestry"]
}

2. 检索文档 GET

检索单个雇员的数据,执行一个HTTP GET请求并指定文档地址-索引库、类型和ID,即可返回原始的JSON文档。

GET megacorp/employee/1

返回

{
  "_index": "megacorp",
  "_type": "employee",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "firstname": "John",
    "lastname": "Smith",
    "age": 25,
    "introduce": "i love to go rock climing",
    "interests": [
      "sports",
      "music"
    ]
  }
}
GET megacorp/employee/2
GET megacorp/employee/3

HTTP命令

  • GET 检索文档
  • PUT 新增文档
  • DELETE 删除文档
  • HEAD 检查文档是否存在

3. 轻量搜索

# 搜索所有雇员
GET megacorp/employee/_search

使用索引库megacorp以及类型employee,返回结果包括3个文档,放在数组hits中。一个搜索默认返回10条结果。

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 1,
    "hits": [
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "2",
        "_score": 1,
        "_source": {
          "firstname": "Jane",
          "lastname": "Smith",
          "age": 32,
          "introduce": "i like to collect rock albums",
          "interests": [
            "music"
          ]
        }
      },
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "1",
        "_score": 1,
        "_source": {
          "firstname": "John",
          "lastname": "Smith",
          "age": 25,
          "introduce": "i love to go rock climing",
          "interests": [
            "sports",
            "music"
          ]
        }
      },
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "3",
        "_score": 1,
        "_source": {
          "firstname": "Douglas",
          "lastname": "Fir",
          "age": 35,
          "introduce": "i like to build cabinets",
          "interests": [
            "forestry"
          ]
        }
      }
    ]
  }
}

需求:搜索姓名为 Smith 的雇员
使用高亮搜索,涉及到查询字符串(query-string_)搜索,通过一个URL参数来传递查询信息给搜索接口。

GET magacorp/employee/_search?q=lastname:Smith

3. 查询表达式搜索

Query-string 搜索通过命令非常方便地进行临时性的即席搜索,但它由自身的局限性。Elasticsearch提供了丰富灵活的查询语言叫做查询表达式。

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

不再使用query-string参数,而使用JSON构造的请求体替代,并使用一个match查询。

4. 复杂的搜索

需求:搜索姓氏为Smitch且年龄大于30的雇员

GET megacorp/employee/_search
{
  "query":{
    "bool":{
      "must":{
        "match":{"lastname":"smith"}
      }
    },
    "filter":{
      "range":{
        "age":{"gt":30}
      }
    }
  }
}

使用range过滤器,找到年龄大于30的文档。

添加了一个过滤器用于执行一个范围查询,并复用之前的match查询。

5. 全文搜索(_search)

需求:搜索所有喜欢攀岩(rock climbing)的雇员

GET megacorp/employee/_search
{
    "query":{
      "match":{
        "introduce":"rock climbing"
      }
    }
}

结果按相关性排序,即每个文档跟查询的匹配程度,第一个最高得分的结果很明显。

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 0.26742277,
    "hits": [
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "2",
        "_score": 0.26742277,
        "_source": {
          "firstname": "Jane",
          "lastname": "Smith",
          "age": 32,
          "introduce": "i like to collect rock albums",
          "interests": [
            "music"
          ]
        }
      },
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "1",
        "_score": 0.26742277,
        "_source": {
          "firstname": "John",
          "lastname": "Smith",
          "age": 25,
          "introduce": "i love to go rock climing",
          "interests": [
            "sports",
            "music"
          ]
        }
      }
    ]
  }
}

6. 短语搜索(match_phrase)

需求:仅匹配同时包含rock和albums,且二者以短语 rock albums 形式紧挨着的雇员记录。

GET megacorp/employee/_search
{
  "query":{
    "match_phrase":{
      "introduce":"rock albums"
    }
  }
}

7. 高亮搜索(highlight)

GET megacorp/employee/_search
{
  "query":{
    "match_phrase":{
      "introduce":"rock albums"
    }
  },
  "highlight": {
    "fields": {
      "introduce": {}
    }
  }
}

返回结果中以HTML的em标签封装

GET megacorp/employee/_search
{
  "query":{
    "match_phrase":{
      "introduce":"rock albums"
    }
  },
  "highlight": {
    "fields": {
      "introduce": {}
    }
  }
}

8. 分析

支持管理这对雇员目录做分析,Elasticsearch聚合(aggregations)允许我们基于数据生成一些精细的分析结果。集合与SQL中的GROUP BY类似,但更强大。

# 挖掘出雇员中最受欢迎的兴趣爱好
GET megacorp/employee/_search
{
  "aggs": {
    "all_interests": {
      "terms": { "field": "interests" }
    }
  }
}

# 查询名叫Smith的雇员中最受欢迎的兴趣爱好可直接添加适当的查询来组合
GET /megacorp/employee/_search
{
  "query": {
    "match": {
      "lastname": "smith"
    }
  },
  "aggs": {
    "all_interests": {
      "terms": {
        "field": "interests"
      }
    }
  }
}
# 查询特定兴趣爱好员工的平均年龄,聚合支持分级汇总
GET /megacorp/employee/_search
{
    "aggs" : {
        "all_interests" : {
            "terms" : { "field" : "interests" },
            "aggs" : {
                "avg_age" : {
                    "avg" : { "field" : "age" }
                }
            }
        }
    }
}

五. 集群内的原理

ElasticSearch 的主旨是随时可用和按需扩容,而扩容可通过购买性能更强大(垂直扩容或纵向扩容)或数量更多的服务器来实现。虽然ES可获益于更强大的硬件设备,但垂直扩容是有限的。真正的扩容能力是来自于水平库扩容 - 为集群添加更多的节点,并将负载压力和稳定分散到节点中。
对于大多数数据库而言,通常需要对应用进行非常大的改动,才能利用上横向扩容和新增资源。ES天生就是分布式的,它知道如何通过管理多节点来提高扩容性和可用性,这也意味着应用无需关注这个问题。

你可能感兴趣的:(ElasticSearch基础)