一、什么是elasticsearch
Elasticsearch是一个基于Lucene的高度可伸缩的分布式的开源全文搜索和分析引擎。它允许您快速、实时地存储、搜索和分析大量数据。它通常用作底层引擎/技术,为具有复杂搜索特性和需求的应用程序提供支持。ElasticSearch是用java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。
二、Elasticsearch的安装和配置
1、下载并解压相应的安装包,并配置ES_HOME下载链接貌似被屏蔽了,需要开代理下载。
2、在bin目录下启动elasticsearch.bat 即可运行Elasticsearch,通过浏览器访问localhost:9200如果返回一串json则说明启动成功。
3、上述的启动ES是基于环境变量JAVA_HOME所指向的JDK,如果要自己指定飞环境变量的JDk可以在环境变量中配置ES_JDK,类似JAVA_HOME,然后修改ES的bin目录下的
elasticsearch-env文件和elasticsearch-env.bat,具体修改如下
4、创建ES服务(注意JAVA_HOME环境变量一定要设置成系统变量,不能设置为用户系统变量,不然启动会报错,无法找到jvm.dll文件)
执行命令elasticsearch-server.bat start 就能将ES创建为windows服务,elasticsearch-server.bat相关的命令有
install 将Elasticsearch作为服务安装
start 启动Elasticsearch服务(如果已安装)
stop 停止Elasticsearch服务(如果启动)
remove 删除已安装的Elasticsearch服务(并在启动时停止服务)
manager 启动一个GUI来管理已安装的服务,可以设置服务的一些属性和参数
elasticsearch-server.bat manager 执行后的界面如下:如果要指向非JAVA_HOME 的jdk,那么可以修改下面的jvm.ddl
三、elasticsearch中的基本概念
概述:
在Elasticsearch中,包含多个索引(Index),相应的每个索引可以包含多个类型(Type),这些不同的类型每个都可以存储多个文档(Document),每个文档又有多个属性。一个索引索引 (index) 类似于传统关系数据库中的一个数据库,是一个存储关系型文档的地方。 索引 (index) 的复数词为 indices 或 indexes 。
1、索引(index): ES将数据存储于一个或多个索引中,索引是具有类似特性的文档的集合。类比传统的关系型数据库领域来说,索引相当于SQL中的一个数据库。索引由其名称(必须为全小写字符)进行标识,并通过引用此名称完成文档的创建、搜索、更新及删除操作。一个ES集群中可以按需创建任意数目的索引。
2、类型(type):类型是索引内部的逻辑分区(category/partition),然而其意义完全取决于用户需求。因此,一个索引内部可定义一个或多个类型(type)。一般来说,类型就是为那些拥有相同的域的文档做的预定义。例如,在索引中,可以定义一个用于存储用户数据的类型,一个存储日志数据的类型,以及一个存储评论数据的类型。类比传统的关系型数据库领域来说,类型相当于“表”。
3、文档(document):文档是Lucene索引和搜索的原子单位,它是包含了一个或多个域的容器,基于JSON格式进行表示。文档由一个或多个域组成,每个域拥有一个名字及一个或多个值,有多个值的域通常称为“多值域”。每个文档可以存储不同的域集,但同一类型下的文档至应该有某种程度上的相似之处。
4、映射(mapping):ES中,所有的文档在存储之前都要首先进行分析。用户可根据需要定义如何将文本分割成token、哪些token应该被过滤掉,以及哪些文本需要进行额外处理等等。另外,ES还提供了额外功能,例如将域中的内容按需排序。事实上,ES也能自动根据其值确定域的类型。
5、节点(node):运行了单个实例的ES主机称为节点,它是集群的一个成员,可以存储数据、参与集群索引及搜索操作。类似于集群,节点靠其名称进行标识,默认为启动时自动生成的随机Marvel字符名称。用户可以按需要自定义任何希望使用的名称,但出于管理的目的,此名称应该尽可能有较好的识别性。节点通过为其配置的ES集群名称确定其所要加入的集群。
6、分片(shard):ES的“分片(shard)”机制可将一个索引内部的数据分布地存储于多个节点,它通过将一个索引切分为多个底层物理的Lucene索引完成索引数据的分割存储功能,这每一个物理的Lucene索引称为一个分片(shard)。每个分片其内部都是一个全功能且独立的索引,因此可由集群中的任何主机存储。创建索引时,用户可指定其分片的数量,默认数量为5个。
7、副本(replica):Shard有两种类型:primary和replica,即主shard及副本shard。Primary shard用于文档存储,每个新的索引会自动创建5个Primary shard,当然此数量可在索引创建之前通过配置自行定义,不过,一旦创建完成,其Primary shard的数量将不可更改。Replica shard是Primary Shard的副本,用于冗余数据及提高搜索性能。每个Primary shard默认配置了一个Replica shard,但也可以配置多个,且其数量可动态更改。ES会根据需要自动增加或减少这些Replica shard的数量。
四、ES相关度评分的理论
1、bool模型:只是在查询中使用 AND
、 OR
和 NOT
(与、或和非)这样的条件来查找匹配的文档,这个过程简单且快速,它将所有可能不匹配的文档排除在外。
2、词频/逆向文档频率(TF/IDF):当匹配到一组文档后,需要根据相关度排序这些文档,不是所有的文档都包含所有词,有些词比其他的词更重要。一个文档的相关度评分部分取决于每个查询词在文档中的 权重 。词的权重由三个因素决定分别是:
词频:词在文档中出现的频率越高权重越高。
逆向文档率:词在所有文档中出现的频率越高,权重越低。
字段长度归一值:字段越短,权重越高。
3、向量空间模型:先将查询条件根据词的权重表示为向量a,然后为被查询的每个文档创建查询词向量b,a的b的夹角越小,相关度越高。
五、elasticsearch中主要的配置说明#集群的名称,集群内的节点cluster.name必须相同
cluster.name: myElasticsearch
#节点名称 node.name: node1
#配置当前节点是否具有可选为master节点的资格,默认值为true node.master: true
#配置当前节点是否允许存储数据,默认值为true node.data: true
master和data同时配置会产生一些奇异的效果:
1) 当master为false,而data为true时,会对该节点产生严重负荷;
2) 当master为true,而data为false时,该节点作为一个协调者;
3) 当master为false,data也为false时,该节点就变成了一个负载均衡器。
#配置节点之间交互的端口 transport.tcp.port: 9300
#设置运行跨域访问,默认为false http.cors.enabled: true
#设置跨域访问的允许范围 http.cors.allow-origin: "*"
#设置访问这个节点的ip和该节点绑定的ip network.host: 192.168.0.1
#是否禁止HTTP http.enabled: false
#HTTP监听的端口 http.port: 9200
#节点间交互时,可以设置是否压缩,转为为不压缩:
transport.tcp.compress: true
#设置新节点被启动时能够发现的主节点列表(主要用于不同网段机器连接) discovery.zen.ping.unicast.hosts: ["192.168.0.1:9300", "192.168.0.1:9301"]
#配置索引的默认分片数,默认值为5 index.number_of_shards: 5
#配置索引的默认副本数,默认值为1 index.number_of_replicas: 1
#配置文件所在的位置,即elasticsearch.yml和logging.yml所在的位置 path.conf: /path/to/conf
#分配给当前节点的索引数据所在的位置 path.data: /path/to/data
#临时文件位置 path.work: /path/to/work
#日志文件所在位置 path.logs: /path/to/logs
#插件安装位置 path.plugins: /path/to/plugins
#设置内容的最大长度:
http.max_content_length: 100mb
六、将数据导入到elasticsearch
1、外部的数据存储在外部文件accounts.json中,里面的数据都是json格式,可以通过下面的命令来进行导入。
curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/account/_bulk?pretty&refresh" --data-binary "@accounts.json"
{"index":{"_id":"1"}}
{"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane",
"employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
{"index":{"_id":"2"}}
{"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street",
"employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"}
2、外部数据存储在mysql中
占位
七、配置elasticsearch集群
1、下载elasticsearch的安装包,并解压3份,然后分别编辑它们的elasticsearch.yml配置文件,再分别启动各个节点,它们会自动发现各个节点并组成集群。
2、注意不要直接复制已经运行过的elasticsearch,因为已经运行的过程中已经产生了数据,所以配置集群后有可能无法链接节点,这个时候清空data目录中的文件应该可以解决。
#############node1####################
cluster.name: elasticsearch node.name: node-1 node.master: true node.data: true
http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 127.0.0.1 http.port: 9201 transport.tcp.port: 9301 discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301", "127.0.0.1:9302", "127.0.0.1:9303"] ###############node2#################### cluster.name: elasticsearch node.name: node-2 node.master: true node.data: true
http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 127.0.0.1 http.port: 9202 transport.tcp.port: 9302 discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301", "127.0.0.1:9302", "127.0.0.1:9303"] #############node3######################## cluster.name: elasticsearch node.name: node-3 node.master: true node.data: true
http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 127.0.0.1
http.port: 9203
transport.tcp.port: 9303
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301", "127.0.0.1:9302", "127.0.0.1:9303"]
集群搭建完成后可以来对集群状态进行查看
3、安装head插件
3.1、head插件是运行在node环境上的,安装head插件前需要安装node.js。
3.2、下载elasticsearch-head-master.zip并解压,然后以命令行的方式进入该文件夹使用npm install来安装。
3.3、安装完成后在该目录下会出现一个文件夹node_modules,进入该文件夹并执行npm run start 来运行。
3.4、访问http://localhost:9100/ 即可看到如下界面。
4、集群中节点的分类
4.1、主节点:首先要将节点设置为候选主节点,候选主节点的设置方法是设置node.mater为true,默认情况下,node.mater和node.data的值都为true。在集群启动后各个节点会在候选节点中选举一个主节点。主节点负责创建索引、删除索引、分配分片、追踪集群中的节点状态等工作。
4.2、数据节点:负责数据的存储和相关具体操作,比如CRUD、搜索、聚合。所以,数据节点对机器配置要求比较高,首先需要有足够的磁盘空间来存储数据,其次数据操作对系统CPU、Memory和IO的性能消耗都很大。通常随着集群的扩大,需要增加更多的数据节点来提高可用性。
4.3、客户端节点:负责请求的分发和汇总,本身并不存储数据。请求的转发和汇总这个功能本身主节点和数据节点也能完成这项工作,但是客户端节点是专门来完成请求的分发和汇总,从而更好的实现负载均衡。
4.4、协调节点:这是一个节点的角色,不管是主节点、数据节点还是客户端节点,只要请求是由哪个节点进行分发和汇总,那么该节点就是承担了协调节点的角色。协调节点对处理器和运行内存要求比较高,客户端节点只能作为协调节点。
5、分片
5.1、主分片(Primary Shard):是elasticsearch的最小存储单元,一个index中的数据通常会存储在多个分片中。默认情况下,elasticsearch会为每个index分为5个分片,可以通过配置文件中index.number_of_shards: 5来对分片数进行设置。分片并不是越多越好,虽然分片查询时并行的,但是请求的分发和结果的合并都需要消耗时间和性能的,所以在数据量比较少的情况下,分片太多反而会降低效率。分片在创建index的时候就已经分配好,并且无法修改。
5.2、复制分片(Replica Shard):主要是进行数据冗余来提高系统的可靠性。
6、集群的状态:
Red,表示有主分片没有分配,某些数据不可用。
Yellow,表示主分片都已分配,数据都可用,但是有复制分片没有分配。
Green,表示主分片和复制分片都已分配,一切正常。
八、安装和使用中文分词器
1、elasticsearch提供了一些内置的分词器,并且默认是使用标准分词器。
1.1、standard analyzer(标准分词器):去标点符号和停用词,将句子直接分成单个字,并将大写转为小写。
POST _analyze { "analyzer": "standard", "text": "中国人,I am CHinese!" }
...
{ "tokens": [ { "token": "中", "start_offset": 0, "end_offset": 1, "type": "<IDEOGRAPHIC>", "position": 0 }, { "token": "国", "start_offset": 1, "end_offset": 2, "type": "<IDEOGRAPHIC>", "position": 1 }, { "token": "人", "start_offset": 2, "end_offset": 3, "type": "<IDEOGRAPHIC>", "position": 2 }, { "token": "i", "start_offset": 4, "end_offset": 5, "type": "<ALPHANUM>", "position": 3 }, { "token": "am", "start_offset": 6, "end_offset": 8, "type": "<ALPHANUM>", "position": 4 }, { "token": "chinese", "start_offset": 9, "end_offset": 16, "type": "<ALPHANUM>", "position": 5 } ] }
1.2、simple analyzer(简单分词器):通过空格和标点符号来进行分词,同时忽略标点符号、数字和停用词,将大写转为小写。
POST _analyze { "analyzer": "simple", "text": "我是 中国人123,I am CHinese" }
...
{ "tokens": [ { "token": "我是", "start_offset": 0, "end_offset": 2, "type": "word", "position": 0 }, { "token": "中国人", "start_offset": 3, "end_offset": 6, "type": "word", "position": 1 }, { "token": "i", "start_offset": 10, "end_offset": 11, "type": "word", "position": 2 }, { "token": "am", "start_offset": 12, "end_offset": 14, "type": "word", "position": 3 }, { "token": "chinese", "start_offset": 15, "end_offset": 22, "type": "word", "position": 4 } ] }
1.3、whitespace analyzer(空格分词器):顾名思义就是根据空格来进行分词。
POST _analyze { "analyzer": "whitespace", "text": "我是 中国人123,I am CHinese" }
...
{ "tokens": [ { "token": "我是", "start_offset": 0, "end_offset": 2, "type": "word", "position": 0 }, { "token": "中国人123,I", "start_offset": 3, "end_offset": 11, "type": "word", "position": 1 }, { "token": "am", "start_offset": 12, "end_offset": 14, "type": "word", "position": 2 }, { "token": "CHinese", "start_offset": 15, "end_offset": 22, "type": "word", "position": 3 } ] }
1.4、language analyzer(语言分词器):elasticsearch内置了多种语言分词器,如english、chinese等。但是分词效果并不理想。
2、安装中文分词器:
2.1、下载比较常用的中文分词器elasticsearch-analysis-ik-6.6.0.zip,注意一定要与elasticsearch的版本严格对应,一个小版本的区别都有可能使用不了。
2.2、将解压后的文件夹放入ES安装目录中的plugins目录下,然后重启ES就算安装成功,注意集群中的每个节点都必须要对分词器进行安装
2.3、ik分词器有两种分词方式ik_smart 和ik_max_word ,前者是粗粒度拆分,后者是细粒度拆分
POST _analyze { "analyzer": "ik_smart", "text": "我是中国人,我爱中国" }
...
{ "tokens": [ { "token": "我", "start_offset": 0, "end_offset": 1, "type": "CN_CHAR", "position": 0 }, { "token": "是", "start_offset": 1, "end_offset": 2, "type": "CN_CHAR", "position": 1 }, { "token": "中国人", "start_offset": 2, "end_offset": 5, "type": "CN_WORD", "position": 2 }, { "token": "我", "start_offset": 6, "end_offset": 7, "type": "CN_CHAR", "position": 3 }, { "token": "爱", "start_offset": 7, "end_offset": 8, "type": "CN_CHAR", "position": 4 }, { "token": "中国", "start_offset": 8, "end_offset": 10, "type": "CN_WORD", "position": 5 } ] }
细粒度拆分:
POST _analyze { "analyzer": "ik_max_word", "text": "我是中国人,我爱中国" }
...
{ "tokens": [ { "token": "我", "start_offset": 0, "end_offset": 1, "type": "CN_CHAR", "position": 0 }, { "token": "是", "start_offset": 1, "end_offset": 2, "type": "CN_CHAR", "position": 1 }, { "token": "中国人", "start_offset": 2, "end_offset": 5, "type": "CN_WORD", "position": 2 }, { "token": "中国", "start_offset": 2, "end_offset": 4, "type": "CN_WORD", "position": 3 }, { "token": "国人", "start_offset": 3, "end_offset": 5, "type": "CN_WORD", "position": 4 }, { "token": "我", "start_offset": 6, "end_offset": 7, "type": "CN_CHAR", "position": 5 }, { "token": "爱", "start_offset": 7, "end_offset": 8, "type": "CN_CHAR", "position": 6 }, { "token": "中国", "start_offset": 8, "end_offset": 10, "type": "CN_WORD", "position": 7 } ] }