ElasticSearch 是一款强大的、开源的、分布式的搜索与分析引擎,简称 ES,它提供了实时搜索聚合分析两大功能。

本文介绍 ES 的安装方法,并导入一组电影数据,可供练习 ES 使用。

1,安装 ES

进入ES 官网下载页面,下载 ES 安装包。

在这里插入图片描述

我这里选择的是 Linux 系统版本,下载完成之后,得到如下安装包:

elasticsearch-8.4.2-linux-x86_64.tar.gz

使用 tar 命令解压,得到解压缩后的目录 /elasticsearch-8.4.2

> tar -xzf elasticsearch-8.4.2-linux-x86_64.tar.gz
> ls
elasticsearch-8.4.2

因为我们本次搭建的 ES 是为了学习使用,一般搭建在自己的电脑上,我这里关闭了 ES 的安全模式,这需要改变配置文件(config/elasticsearch.yml)中的几个配置值:

在这里插入图片描述

然后使用如下命令启动 ES:

./elasticsearch

使用浏览器访问地址 http://localhost:9200(ES 的默认端口是 9200),如果出现如下结果,则说明启动成功:

{
  "name" : "lenove",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "j47FJULJQm-irccpoT_OZw",
  "version" : {
    "number" : "8.4.2",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "89f8c6d8429db93b816403ee75e5c270b43a940a",
    "build_date" : "2022-09-14T16:26:04.382547801Z",
    "build_snapshot" : false,
    "lucene_version" : "9.3.0",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

2,安装 Kibana

这里安装 Kibana,主要使用它的 Dev-Tools 来写 ES 的 DSL 语句。

首先进入 Kibana 下载页面,下载 Kibana:

在这里插入图片描述

下载完成后,得到如下安装包:

kibana-8.4.2-linux-x86_64.tar.gz

使用 tar 命令解压即可:

> tar -xzf kibana-8.4.2-linux-x86_64.tar.gz
> ls
kibana-8.4.2

使用如下命令启动 Kibana:

./kibana

注意,在启动 Kibana 之前,要先启动 ES,Kibana 会自动连接上已启动的 ES。

启动完成后,访问地址 http://localhost:5601/app/dev_tools(Kibana 的端口默认是 5601),可进入如下页面:

在这里插入图片描述

到目前为止,ES 和 Kibana 都已安装,下面我们来导入一组数据。

3,获取电影数据

我在这里准备了200 多条电影数据,每条电影数据包含多个字段,比如:

{
    "publish_time": "1994-09-10",
    "movie_time": "142",
    "other_name": "月黑高飞(港) / 刺激1995(台) / 地狱诺言 / 铁窗岁月 / 消香克的救赎",
    "year": "1994",
    "classifications": "剧情/犯罪",
    "score": "9.7",
    "language": "英语",
    "title": "肖申克的救赎 / The Shawshank Redemption / 月黑高飞(港)  /  刺激1995(台)",
    "introduction": "一场谋杀案使银行家安迪(蒂姆•罗宾斯 Tim Robbins 饰)蒙冤入狱,谋杀妻子及其情人的指控将囚禁他终生。在肖申克监狱的首次现身就让监狱“大哥”瑞德(摩根•弗里曼 Morgan Freeman 饰)对他另眼相看。瑞德帮助他搞到一把石锤和一幅女明星海报,两人渐成患难 之交。很快,安迪在监狱里大显其才,担当监狱图书管理员,并利用自己的金融知识帮助监狱官避税,引起了典狱长的注意,被招致麾下帮助典狱长洗黑钱。偶然一次,他得知一名新入狱的小偷能够作证帮他洗脱谋杀罪。燃起一丝希望的安迪找到了典狱长,希望他能帮自己翻案。阴险伪善的狱长假装答应安迪,背后却派人杀死小偷,让他唯一能合法出狱的希望泯灭。沮丧的安迪并没有绝望,在一个电闪雷鸣的风雨夜,一场暗藏几十年的越狱计划让他自我救赎,重获自由!老朋友瑞德在他的鼓舞和帮助下,也勇敢地奔向自由。本片获得1995年奥...",
    "country": "美国",
    "directors": "弗兰克·德拉邦特",
    "writers": "弗兰克·德拉邦特 / 斯蒂芬·金",
    "actors": "蒂姆·罗宾斯 / 摩根·弗里曼 / 鲍勃·冈顿 / 威廉姆·赛德勒 / 克兰西·布朗 / 吉尔·贝罗斯 / 马克·罗斯顿 / 詹姆斯·惠特摩 / 杰弗里·德曼 / 拉里·布兰登伯格 / 尼尔·吉恩托利 / 布赖恩·利比 / 大卫·普罗瓦尔 / 约瑟夫·劳格诺 / 祖德·塞克利拉 / 保罗·麦克兰尼 / 芮妮·布莱恩 / 阿方索·弗里曼 / V·J·福斯特 / 弗兰克·梅德拉诺 / 马克·迈尔斯 / 尼尔·萨默斯 / 耐德·巴拉米 / 布赖恩·戴拉特 / 唐·麦克马纳斯",
    "img_url": "https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp"
}

每个字段的含义如下:

字段名称 含义 字段名称 含义
publish_time 发布时间 title 电影名称
movie_time 电影时长 introduction 电影简介
other_name 电影别名 country 发行国家
year 发布年份 directors 导演
classifications 电影分类 writers 编剧
score 电影评分 actors 主演
language 语言 img_url 封面地址

其中的字段 other_nameclassificationstitlewritersactors 都是用斜杠分割。

将上面的数据保存本地,文件名命名为 movies.txt

使用如下 Python 程序预处理数据:

import json

def read_file(file_name):
    f = open(file_name)
    lines = f.readlines()

    for line in lines:
        try:
            line = json.loads(line)
        except Exception as e:
            continue

        yield line

def transform_data(data):
    other_name = data['other_name']
    classifications = data['classifications']
    title = data['title']
    writers = data['writers']
    actors = data['actors']

    # 转成数组
    other_name = [i.strip() for i in other_name.split('/')]
    classifications = [i.strip() for i in classifications.split('/')]
    title = [i.strip() for i in title.split('/')]
    writers = [i.strip() for i in writers.split('/')]
    actors = [i.strip() for i in actors.split('/')]

    data['other_name'] = other_name
    data['classifications'] = classifications
    data['title'] = title
    data['writers'] = writers
    data['actors'] = actors

if __name__== "__main__":
    index = {"index":{"_index":"movies"}} 

    for data in read_file('./movies.txt'):
        transform_data(data)
        
        print(json.dumps(index))
        print(json.dumps(data, ensure_ascii=False))

经过 Python 处理的数据,我放在了这里

4,创建 movies 索引

我们将创建如下结构的 movies 索引:

PUT movies
{
	"mappings" : {
      "properties" : {
        "publish_time" : {
          "type" : "date"
        },
        "movie_time" : {
          "type" : "integer"
        },
        "other_name" : {
          "type" : "keyword"
        },
        "year" : {
          "type" : "integer"
        },
        "classifications" : {
          "type" : "keyword"
        },
        "score" : {
          "type" : "float"
        },
        "language" : {
          "type" : "keyword"
        },
        "title" : {
          "type" : "keyword"
        },
        "introduction" : {
          "type" : "text"
        },
        "country" : {
          "type" : "keyword"
        },
        "directors" : {
          "type" : "keyword"
        },
        "writers" : {
          "type" : "keyword"
        },
        "actors" : {
          "type" : "keyword"
        },
        "img_url" : {
          "type" : "keyword"
        }
      }
    }
}

将上面的 mapping 复制到 Kibana 的 Dev-Tools 中,然后执行 PUT movies 请求即可,到此 movies 索引就构建成功。

5,导入 movies 数据

得到 movies 数据后,将数据放入文件movies.json中,然后执行下面命令将数据导入 ES 中:

curl -s -XPOST "localhost:9200/_bulk?pretty" -H  "Content-Type: application/json" --data-binary "@movies.json"

到此,我们就有了 movies 索引,可以使用 Dev-Tools 对其进行数据分析。

6,使用 Dev-Tools

下面我写了一些 ES DSL 语句对数据进行分析,你可以将这些语句复制到 Dev-Tools 中,然后执行每个请求,实际感受下 ES 分析数据的能力。

GET /_cluster/health            // 查看集群健康状态
GET /_cat/nodes?v	        // 查看集群节点信息
GET /_cat/indices?v	        // 查看索引信息

HEAD movies                     // 判断是否存在 movies 索引

GET movies			// 查看索引的 mappings 和 settings 信息

GET movies/_search	        // 查看索引中的数据
{ 
  "size": 300,
  "_source": ["title", "publish_time"], 
  "query":{
    "match_all":{}
  }
}

POST movies/_search		// 桶聚合分析
{
    "size": 0,
    "aggs": {
        "my_agg": {	
            "terms": {
                "field":"year",
                "size": 1000, 
                "min_doc_count": 10
            }
        } 
    }
}

POST movies/_search		// histogram 聚合分析
{
  "size": 0,
  "aggs": {
    "year_histrogram": {   
      "histogram": {        
        "field":"year",
        "interval":10,     
        "extended_bounds":{
          "min":1920,
          "max":2022
        }
      }
    }
  }
}

POST movies/_search		// date_histogram 聚合分析
{
  "size": 13,
  "_source": ["publish_time", "movie_time"], 
  "query": {
    "range": {
      "publish_time": {
        "gte": "2009-06-01",
        "lte": "2010-01-01"
      }
    }
  }, 
  "aggs": {
    "publish_time_histrogram": {   
      "date_histogram": {        
        "field":"publish_time",    
        "calendar_interval": "year",     
        "format": "yyyy-MM-dd",
        "min_doc_count": 3,
        "extended_bounds":{
          "min":"2009-01-01",
          "max":"2010-01-01"
        }
      },
      "aggs": {
        "total_time": {
          "sum": {
            "field": "movie_time"
          }
        }
      }
    }
  }
}

更多的 ES 命令可以参考 ElasticSearch 命令参考

(本节完。)