【实战】手把手教你使用 Elasticsearch 实现海量级数据搜索(上)

2022-12-04 11:16:46 浏览数 (1)

一、简介

Elasticsearch(简称ES)是一个基于Apache Lucene™的开源搜索引擎,无论在开源还是专有领域,Lucene 可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

对于初次接触 Elasticsearch,不禁会发出一个疑问,Elasticsearch 是干啥的?

官方的解释如下:Elasticsearch(简称ES)是一个基于 Apache Lucene™ 的开源搜索引擎,它提供了一个基于 RESTful web 接口的分布式多用户能力的全文搜索引擎,能够达到实时搜索、稳定、可靠、快速、安装使用方便等特点。

Elasticsearch 的底层数据存储和搜索,是基于 Lucene 进行开发的,那 Lucene 又是啥呢?

Lucene 是 java 领域迄今为止最先进、性能最好的、功能最全的搜索引擎库

如果你之前了解过或者使用过 Lucene,那么在学习 Elasticsearch 会非常的容易,甚至你会发现很多的 Elasticsearch 的 查询语法和 Lucene 的查询语法有很多的相似之处。

今天我们主要是介绍 Elasticsearch 的用法,在后续的文章中,我们也会给大家介绍 Lucene 的玩法。

在介绍 Elasticsearch 的 RESTful API 之前,我们先简单的了解一下 Elasticsearch 中几个重要的概念。

  • 索引 (indices ):类似于我们的关系型数据库
  • 类型(type ):类似于数据库的表结构
  • 文档(Document ):类似于数据库表中的行,也就是具体的数据
  • 字段(Field ):雷雨时数据库表中的列

不过,这里有一个非常坑的地方,es 版本号的不同,其中的内部结构和对外的 API 差别也很大,各版本号差别如下:

  • es5 版本:允许一个索引库下中可以创建多个类型
  • es6 版本:一个索引库下中只能创建一种类型
  • es7 版本:一个索引库不支持显式创建类型,当创建索引的时候,默认会创建一个名称为_doc的类型

为什么在高版本里面,es 不支持创建多个类型呢?

因为一个索引库下,如果多个类型,会存在搜索问题,比如,类型 A 下某个字段order_source是一个long型;类型 B 下,字段order_source是一个text型。

这两个字段名称都是一样,实际存入 Lucene 中,也是同一个字段,但是他们的字段类型是不一样的,要么是long型,要么是text型,只会是其中一个,这就造成一个问题,类型 A 中order_source字段不可用,或者类型 B 中order_source字段不可用。

因此,在新版本中,索引下的类型,有且只有一个!

了解了 Elasticsearch 的基本概念之后,下面我们一起开启 Elasticsearch 实战操作!

二、服务安装

首先,在使用 Elasticsearch 之前,我们需要先安装好服务,操作也很简单。

为了和真实环境一致,我们采用CentOS7来部署 ElasticSearch 服务。

建议把所需的安装包,手动从网上下载下来,因为服务器下载 ElasticSearch 安装包速度像蜗牛……,非常非常慢~~,可能是国内的网络原因吧!

登录https://www.elastic.co/cn/downloads/elasticsearch,选择相应的系统环境下载软件包,小编我采用的是CentOS,所以选择Linux环境。

2.1、安装JDK(已经安装过,可以跳过)

Elasticsearch 是用 Java 语言开发的,所以在安装之前,需要先安装一下JDK

代码语言:javascript复制
yum -y install java-1.8.0-openjdk

查看java安装情况

代码语言:javascript复制
java -version
2.2、安装ElasticSearch

进入到对应上传的文件夹,安装ElasticSearch

代码语言:javascript复制
rpm -ivh elasticsearch-6.1.0.rpm

查找安装路径

代码语言:javascript复制
rpm -ql elasticsearch

一般是装在/usr/share/elasticsearch/下。

2.3、设置data的目录

创建/data/es-data目录,用于elasticsearch数据的存放

代码语言:javascript复制
mkdir -p /data/es-data

修改该目录的拥有者为elasticsearch

代码语言:javascript复制
chown -R elasticsearch:elasticsearch /data/es-data
2.4、设置log的目录
代码语言:javascript复制
mkdir -p /log/es-log

修改该目录的拥有者为elasticsearch

代码语言:javascript复制
chown -R elasticsearch:elasticsearch /log/es-log
2.5、修改配置文件elasticsearch.yml
代码语言:javascript复制
vim /etc/elasticsearch/elasticsearch.yml

修改如下内容:

代码语言:javascript复制
#设置节点名称
cluster.name: my-es

#设置data存放的路径为/data/es-data
path.data: /data/es-data

#设置logs日志的路径为/log/es-log
path.logs: /log/es-log

#设置内存不使用交换分区,配置了bootstrap.memory_lock为true时反而会引发9200不会被监听,原因不明
bootstrap.memory_lock: false

#设置允许所有ip可以连接该elasticsearch
network.host: 0.0.0.0

#开启监听的端口为9200
http.port: 9200

#增加新的参数,为了让elasticsearch-head插件可以访问es (5.x版本,如果没有可以自己手动加)
http.cors.enabled: true
http.cors.allow-origin: "*"
2.6、启动elasticsearch

启动

代码语言:javascript复制
systemctl start elasticsearch

查看状态

代码语言:javascript复制
systemctl status elasticsearch

设置开机启动

代码语言:javascript复制
systemctl enable elasticsearch

启动成功之后,测试服务是否开启

代码语言:javascript复制
curl -X GET http://localhost:9200

返回如下信息,说明安装、启动成功了

同时也可以远程测试一下,如果网络被拒绝,检查防火墙是否开启

代码语言:javascript复制
#查询防火墙状态
firewall-cmd --state

如果状态是active表示已经开启,可以将其关闭

代码语言:javascript复制
#关闭防火墙
systemctl stop firewalld.service

如果不想开机启动,可以输入如下命令

代码语言:javascript复制
#禁止firewall开机启动
systemctl disable firewalld.service

我们再来测试一下远程是否可以正常访问,结果如下:

已经可以正常访问了。

三、可视化界面管理

Elasticsearch 服务安装完成之后,有没有工具,可以通过页面管理直接查询呢?

答案肯定是有的,以chrome为例,访问https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm?hl=zh-CN这个地址,在线安装ElasticSearch Head插件,也可以在先下载这个插件,然后离线安装。

打开ElasticSearch Head插件,输入 Elsaticsearch 服务器的地址,然后连接,就可以可视化查看 es 内部存储的数据了

四、索引 API 介绍

下面以 ElasticSearch 的6.8.2版本为例,给大家介绍 API 的使用。

4.1、创建索引

Elsaticsearch 创建索引非常的简单,通过put方式,只需要填写好地址就可以创建,以创建一个user_index索引为例,请求方式如下:

4.2、查询索引

通过get请求,就可以直接获取当前索引信息。

4.3、删除索引

通过delete请求,就可以直接删除索引信息。

4.4、创建类型

如果我们想要在索引下创建类型,可以通过如下方式实现。

例如,在索引下创建一个名为user_type的类型,字段映射结构如下:

代码语言:javascript复制
{
    "properties":{
        "name":{
            "type":"text",
            "index":true
        },
        "sex":{
            "type":"keyword",
            "index":true
        },
        "mobile":{
            "type":"keyword",
            "index":false
        }
    }
}
4.5、查询类型

put请求改成get,就可以查询我们刚刚创建的类型了。

详细的内容如下:

代码语言:javascript复制
{
    "user_index": {
        "mappings": {
            "user_type": {
                "properties": {
                    "mobile": {
                        "type": "keyword",
                        "index": false
                    },
                    "name": {
                        "type": "text"
                    },
                    "sex": {
                        "type": "keyword"
                    }
                }
            }
        }
    }
}

Elasticsearch 支持的数据类型非常的多,本文只使用字符串型的textkeyword,其中text类型支持分词,而keyword不支持分词查询,在实际的使用过程中,大家根据自己的业务情况,对数据类型采用合适的值。

四、文档 API 介绍

Elasticsearch 使用最频繁的部分,当属文档 API 操作,下面我们一起来看看具体的实践。

4.1、创建文档

通过 restful 方式创建,其中末尾可以指定主键 ID,多次执行如果 主键ID 存在就更新,否则插入。

4.2、通过主键 ID 查询文档

只需要将post改成get即可!

4.3、更新文档(指定字段)

url末尾加上_update,就可以执行修改请求!

4.4、通过主键 ID 删除文档

将请求类型改成delete,就可以删除文档!

4.5、查询文档-查询所有

url后面加上_search,就可以查询所有文档数据

4.6、查询文档-返回指定列

通过在请求参数中配置"_source" : [字段1,字段2],可以返回指定列。

请求参数如下:

代码语言:javascript复制
{
   "query" : {
       "match_all" : {

       }
   },
   "_source" : ["name","sex"]
}

返回结构,和上面类似!

4.7、查询文档-字段排序

通过在请求参数中配置sort,可以对字段内容进行排序返回。

请求参数如下:

代码语言:javascript复制
{
    "query" : {
       "match_all" : {

       }
   },
   "sort" : {
       "_id":{
           "order" : "asc"
       }
   }
}

返回结构,和上面类似!

4.8、查询文档-分页查询

通过在请求参数中配置fromsize,就可以进行分页查询了。

  • from:表示第几行,默认从0开始
  • size:表示返回多少数据

请求参数如下:

代码语言:javascript复制
{
    "query" : {
       "match_all" : {

       }
   },
   "from" : 0,
   "size" : 2
}
4.9、查询文档-某个字段精准匹配查询

通过match可以实现对字段内容的查询。

请求参数如下:

代码语言:javascript复制
{
   "query" : {
       "match" : {
           "name" : "张里"
       }
   }
}
4.10、查询文档-多条件查询 - and

如果需要多个条件组合查询,可以通过boolmust结合查询

代码语言:javascript复制
{
    "query":{
        "bool":{
            "must":[
                {
                    "match":{
                        "name":"张"
                    }
                },
                {
                    "match":{
                        "sex:"男"
                    }
                }
            ]
        }
    }
}
4.11、查询文档-多条件查询 - or

如果需要多个条件组合查询,可以通过boolshould结合查询

代码语言:javascript复制
{
    "query":{
        "bool":{
            "should":[
                {
                    "match":{
                        "name":"张"
                    }
                },
                {
                    "match":{
                        "sex:"男"
                    }
                }
            ]
        }
    }
}
4.12、查询文档-多条件查询 - 大于/小于

如果需要多个条件组合查询,可以通过bool配置实现filter -> range关系查询

代码语言:javascript复制
{
    "query":{
        "bool":{
            "filter":{
                "range":{
                    "age":{
                        "gt" : 25,
                        "lt" : 50
                    }
                }
            }
        }
    }
}
4.13、查询文档-聚合查询 - group by

可以通过aggs -> terms实现对某个字段进行聚合查询,比如下面这个配置,查询具有相同年龄的用户数。

代码语言:javascript复制
{
    "aggs":{
        "age_group":{
            "terms":{
                "field":"age"
            }
        }
    },
    "size" : 0
}
4.14、查询文档-聚合查询 - avg

可以通过aggs -> avg实现对某个字段进行聚合查询,比如下面这个配置,查询具有用户的年龄平均值。

代码语言:javascript复制
{
   "aggs" : { //聚合操作
       "age_avf" : { //名称,自定义
           "avg" : { //分组
               "field" : "age" //分组字段
           }
       }
   },
   "size" : 0
}
4.15、查询文档-聚合查询 - sum

可以通过aggs -> sum实现对某个字段进行聚合查询,比如下面这个配置,查询具有用户的年龄总数。

代码语言:javascript复制
{
   "aggs" : { //聚合操作
       "age_sum" : { //名称,自定义
           "sum" : { //分组
               "field" : "age" //分组字段
           }
       }
   },
   "size" : 0
}

五、小结

本文主要是围绕 ElsaticSearch 的 restful api 做了一个简单的介绍,在下篇文章中,我们会重点介绍 SpringBoot 整合 ElsaticSearch 的实战玩法。

内容难免有所遗漏,欢迎大家批评指出!

0 人点赞