Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。
特点:
分布式的实时文件存储,每个字段都被索引并可被搜索
分布式的实时分析搜索引擎库(可做不规则查询)
可以扩展到上百台服务器,处理PB级结构化或非结构化数据
Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
ES能做什么?
全文检索(全部字段;值--->数据)、模糊查询(搜索)、数据分析(提供分析语法,例如聚合)
数仓--分析处理--hbase/mysql--es--(分析、检索、搜索、javaee前端可视化)
mysql--->Json(脚本)--->ES
Solr、ElasticSearch、 Hermes(腾讯开发;主要用于实时检索分析,处理数据量庞大)3者的区别:
Solr、ES(都可以做全文检索、搜索、分析,基于lucene)
①. 源自搜索引擎,侧重搜索与全文检索。
②. 数据规模从几百万到千万不等,数据量过亿的集群特别少。
有可能存在个别系统数据量过亿,但这并不是普遍现象(就像Oracle的表里的数据规模有可能超过Hive里一样,但需要小型机)。
Hermes
①. 一个基于大索引技术的海量数据实时检索分析平台。侧重数据分析。
②. 数据规模从几亿到万亿不等。最小的表也是千万级别。
在 腾讯17 台TS5机器,就可以处理每天450亿的数据(每条数据1kb左右),数据可以保存一个月之久。
Solr、ES区别
①. Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
②. Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
③. Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
④. Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch
Lucene是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎
搜索引擎产品简介
安装Centos7、建议内存2G以上、安装java1.8环境
设置IP地址
查看自己电脑的网关号
C:\Users\Administrator>ipconfig 以太网适配器 VMware Network Adapter VMnet1: 连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::7d9a:22ee:77c9:3781%18 IPv4 地址 . . . . . . . . . . . . : 192.168.174.1 子网掩码 . . . . . . . . . . . . : 255.255.255.0 默认网关. . . . . . . . . . . . . : 以太网适配器 VMware Network Adapter VMnet8: 连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::29bd:7dab:56c2:ec50%19 IPv4 地址 . . . . . . . . . . . . : 192.168.1.5 子网掩码 . . . . . . . . . . . . : 255.255.255.0 默认网关. . . . . . . . . . . . . : 192.168.1.2
vi /etc/sysconfig/network-scripts/ifcfg-ens33
DEVICE="ens33" ONBOOT="yes" IPADDR="192.168.1.0" PREFIX="24" GATEWAY="192.168.1.2" DNS1="114.114.114.114" IPV6_PRIVACY="no"
改成自己的网关(GATEWAY)
# 网络重置
service network restart
添加用户
[root@localhost ~]# adduser elk [root@localhost ~]# passwd elk
以下授权步骤可省略
[root@localhost ~]# whereis sudoers sudoers: /etc/sudoers.d /etc/sudoers /usr/share/man/man5/sudoers.5.gz [root@localhost ~]# ls -l /etc/sudoers -r--r-----. 1 root root 3960 Jul 15 2018 /etc/sudoers [root@localhost ~]# vi /etc/sudoers ## Allow root to run any commands anywhere root ALL=(ALL) ALL linuxidc ALL=(ALL) ALL ## Allows members of the ‘sys‘ group to run networking, software,
[root@localhost ~]# chmod -v u-w /etc/sudoers
[root@localhost ~]# su elk
解压安装包
[root@localhost jdk1.8]# tar -zxvf jdk-8u171-linux-x64.tar.gz
设置Java环境变量
[root@localhost jdk1.8.0_171]# vi /etc/profile
在文件最后添加
export JAVA_HOME=/home/elk1/jdk1.8/jdk1.8.0_171 export JRE_HOME=$JAVA_HOME/jre export CLASSPATH=.:$JAVA_HOME/LIB:$JRE_HOME/LIB:$CLASSPATH export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
[root@localhost jdk1.8.0_171]# source /etc/profile [root@localhost jdk1.8.0_171]# java -version java version "1.8.0_171"
[root@localhost elasticserach]# tar -zxvf elasticsearch-6.3.1.tar.gz [root@localhost elasticserach]# cd elasticsearch-6.3.1/bin [root@localhost bin]# ./elasticsearch can not run elasticserach as root [root@localhost bin]# su elk [elk@localhost bin]$ ./elasticsearch javo.nio.fileAccessDeniedException:/home/elk/elasticsearch/elasticsearch-6.3.1/config/jvm.options [root@localhost bin]# chown -R elk:elk /home/elk1/elasticsearch ##要在root账户下授权! [elk@localhost config]$ vi jvm.options ##改成2g ## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html ## for more information ## ################################################################ # Xms represents the initial size of total heap space # Xmx represents the maximum size of total heap space -Xms2g -Xmx2g [elk@localhost bin]$ ./elasticsearch [2019-03-23T05:22:00,380][INFO ][o.e.n.Node ] [dbaiLyW] initialized [2019-03-23T05:22:00,380][INFO ][o.e.n.Node ] [dbaiLyW] starting ... 在另外一个窗口: [root@localhost jdk1.8.0_171]# curl 127.0.0.1:9200 { "name" : "dbaiLyW", "cluster_name" : "elasticsearch", "cluster_uuid" : "vm5Jpe7OTE-GdV4nUb5q1w", "version" : { "number" : "6.3.1", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "eb782d0", "build_date" : "2018-06-29T21:59:26.107521Z", "build_snapshot" : false, "lucene_version" : "7.3.1", "minimum_wire_compatibility_version" : "5.6.0", "minimum_index_compatibility_version" : "5.0.0" }, "tagline" : "You Know, for Search" }
#后台启动 [elk@localhost bin]$ ./elasticsearch -d #关闭程序 [elk@localhost bin]$ ps -ef|grep elastic [elk@localhost bin]$ kill 10097
#设置浏览器访问
[root@localhost bin]systemctl stop firewalld [root@localhost bin]vi config/elasticsearch.yml ##改下地址 # ---------------------------------- Network ----------------------------------- # # Set the bind address to a specific IP (IPv4 or IPv6): # network.host: 192.168.1.0
若出现bootstrap checks failed
[root@localhost bin]# vi /etc/security/limits.conf * hard nofile 65536 * soft nofile 131072 * hard nproc 4096 * soft nproc 2048 # End of file 解释说明: nofile - 打开文件的最大数目 noproc - 进程的最大数目 soft 指的是当前系统生效的设置值 hard 表明系统中所能设定的最大值 [root@localhost bin]# vi /etc/sysctl.conf # For more information, see sysctl.conf(5) and sysctl.d(5). vm.max_map_count=655360 fs.file-max=655360 参数解释说明: vm.max_map_count=65530,因此缺省配置下,单个jvm能开启的最大线程数为其一半 file-max是设置 系统所有进程一共可以打开的文件数量
# 测试
Liunx执行: curl ‘http://192.168.1.0:9200/?pretty‘
浏览器访问:http://192.168.1.0:9200/?pretty
1、基于HTTP协议,以JSON为数据交互格式的RESTful API(请求方式:GET/POST/PUT/DELETE/HEAD)
# 状态查看命令 语法:ip:post/_cat/[args](?v|?format=json&pretty) (?v表示显示字段说明,?format=json&pretty表示显示成json格式) 1、查看所有索引 GET _cat/indices?v 2、查看es集群状态 GET _cat/health?v
http://192.168.1.0:9200/_cat 在浏览器中输入可以看到它的一些命令
http://192.168.1.0:9200/_cat/health 查看健康状态;
2、Elasticsearch官方提供了多种程序语言的客户端—java,Javascript,.NET,PHP,Perl,Python,以及 Ruby——还有很多由社区提供的客户端和插件
安装配置Kibana
[elk@localhost soft]$ tar -zxvf kibana-6.3.1-linux-x86_64.tar.gz -C /home/elk/kibana/ # The default is ‘localhost‘, which usually means remote machines will not be able to connect. # To allow connections from remote users, set this parameter to a non-loopback address. server.host: "192.168.1.0" # The URL of the Elasticsearch instance to use for all your queries. elasticsearch.url: "http://192.168.1.0:9200" # Kibana uses an index in Elasticsearch to store saved searches, visualizations and # dashboards. Kibana creates a new index if the index doesn‘t already exist. kibana.index: ".kibana" ##把它打开,创建index索引
[elk@localhost ~]$ cd kibana/kibana-6.3.1-linux-x86_64/bin/ [elk@localhost bin]$ ./kibana 在浏览器中访问: http://192.168.1.0:5601/
创建文档语句
PUT atguigu/doc/0 { "name":"zhangsan", "age":10 }
_index:文档所在索引名称;
_type:文档所在类型名称;
_id:文档唯一id
_uid:组合id,由_type和_id组成(6.x后,_type不再起作用,同_id)
_source:文档的原始Json数据,包括每个字段的内容
_all:将所有字段内容整合起来,默认禁用(用于对所有字段内容检索)
数据的插入用PUT,用文档的方式进行数据的存储;
1)面向文档
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。
面向对象(表)是基于二维表(行列excel)的存储模型-如mysql,操作数据时把它当做一个对象,创建封装对象;写sql语句,查询等
面向对象:表 id name age 1 kris 22 2 alex 18 面向文档:单条 ---------------------- 1 kris 22 ; -------------------------------- 2 alex 18; ----------------------------
面向文档(单条)是一条一条的,多个文档在一块,以单条数据位单位;json字符串,可直接进行操作如.split(“ ”);遍历等
2)JSON
ELasticsearch使用Javascript对象符号(JavaScript Object Notation),也就是JSON,作为文档序列化格式。JSON现在已经被大多语言所支持,而且已经成为NoSQL领域的标准格式。它简洁、简单且容易阅读。更方便的堆数据进行操作;更方便的分词,全文检索、搜索等
以下使用JSON文档来表示一个用户对象:
{ "email": "john@smith.com", "first_name": "John", "last_name": "Smith", "info": { "bio": "Eco-warrior and defender of the weak", "age": 25, "interests": [ "dolphins", "whales" ] }, "join_date": "2014/05/01" }
index--->①建库 type-->②建表 field-->③字段 document-->存储数据的基本单元;
6.0之后,一个index中只能有一个type,
一个type中有多个文档,
一个document中有多个field字段
ES6.0之后就不能运行有type2了!!
在Es6.0之后,一个index中只运行有1个type,弱化了表的概念;(有可能把type取消掉,完全的面向文档)
{ "_index": "kris", "_type": "doc", "_id": "3", "_score": 0.2876821, "_source": { "test2": "haha helo", "first_name": "Douglas", "last_name": "Fir", "age": 35, "about": "I like to build cabinets", "interests": [ "forestry" ] } }
version乐观锁---控制版本号;每次更新数据时,version数值会不一样;
名词解释 ? 索引 index 一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。 ? 类型 type 在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。 ? 字段Field 相当于是数据表的字段,对文档数据根据不同属性进行的分类标识 ? document 一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。
Mysql : select * from user where id = 1;
ES : GET /kris/doc/1 ;可以把/kris/doc理解为表名user,检索id=1的;
Mysql : select * from user;
ES : GET /kris/doc/_search GET /megacorp/employee/_search
ES : GET /megacorp/employee/_search?q=haha (查询字段中带有haha的数据,q相当于关键字,haha为值)
查询出所有文档字段值为haha的文档;
ES : GET /megacorp/employee/_search?q=hello (只要字段中包含hello,不管前边后边有什么值都可以查询到)
查询出所有文档字段值包含hello的文档;mysql中的模糊查询(会影响性能,索引就不能使用了;)不规则匹配查询;搜索;
search: 关键字;对关键字分词;
分词-->在资源库(比如百度,对分词在资源库中进行批评)中做一个全文搜索;
在资源库中也会有一个分词(每个字段都会进行分词);
倒排索引:(值---关键字(id的集合等)去匹配倒排索引---->数据文档(得到每一个具体的文档的ID));用值去找文档ID即倒排索引;
分词: k1: v1, k1: v1,v2, k1: v3 倒排索引: v1:1, 2 v2:2 (只有第二个中有这个值) v3:3
正排索引和倒排索引:
l 正排索引
记录文档Id到文档内容、单词的关联关系
l 倒排索引
记录单词到文档id的关联关系,包含:
单词词典(Term DicTionary):记录所有文档的单词,一般比较大;通过某个字--->数据
倒排索引(Posting List):记录单词倒排列表的关联信息
如搜索硅谷Term Dictionary 硅谷
Posting List
DocId TF Position Offset 1 1 0 <0,2> 3 1 0 <0,2>
DocId:文档id,文档的原始信息
TF:单词频率,记录该词在文档中出现的次数,用于后续相关性算分(评分,想把搜索内容靠前些,即可把评分高点就会靠前了;)
Position:位置(文档),记录Field分词后,单词所在的位置,从0开始;北京 是 最 漂亮 的,北京在0位;
Offset:偏移量,记录单词在文档中开始和结束位置,用于高亮显示等
分词后(通过B+Tree)就可以高效查询;
https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html
每个文档字段都有自己的倒排索引
比如:北京 是 最 漂亮 的
每个值都会通过算法计算出一个值,那句话中某个值去搜索,它会先去顶点,如果比这个值(最)大就看左边(是),比它大就在左边(北京);
通过北京这个词就可以看到倒排索引,id、TF、Position、Offset等; B+Tree每个单元最多2个
它的所有数据都保存在最后一层的节点上,每两个节点之间会有一个链表(一个指向);可以递归获取这个值;
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html
分词是指将文本转换成一系列单词(term or token)的过程,也可以叫做文本分析,在es里面称为Analysis
过滤
Character Filter 对原始文本进行处理 例:去除html标签、特殊字符等
Tokenizer 将原始文本进行分词 例:培训机构-->培训,机构
Token Filters 分词后的关键字进行加工 例:转小写、删除语气词、近义词和同义词等
l 分词API 分词器依赖索引
1)、直接指定测试(指定分词器)
POST _analyze { "analyzer":"standard", "text": "we are family" } 与倒排索引相对应: { "tokens": [ { "token": "we", "start_offset": 0, ###we,前闭后开的区间[ ) "end_offset": 2, "type": "<ALPHANUM>", "position": 0 }, { "token": "are", "start_offset": 3, "end_offset": 6, "type": "<ALPHANUM>", "position": 1 }, { "token": "family", "start_offset": 7, "end_offset": 13, "type": "<ALPHANUM>", "position": 2 } ] }
2)、针对索引的字段进行分词测试(利用该字段的分词器);主要用于测试
GET /kris/doc/_search?q=like 可以搜索出来;--> PUT创建时就已经按照一定规则分词了,
默认的分词器
POST atguigu/_analyze { "field": "name", "text":"hello world" }
POST atguigu/_analyze { "field": "about", ##about可检测出默认的分词器 "text":"we are family" "text":"we are fam?ily" 会把? 两边的分成2部分; }
{ "tokens": [ { "token": "we", "start_offset": 0, "end_offset": 2, "type": "<ALPHANUM>", "position": 0 }, { "token": "are", "start_offset": 3, "end_offset": 6, "type": "<ALPHANUM>", "position": 1 }, { "token": "family", "start_offset": 7, "end_offset": 13, "type": "<ALPHANUM>", "position": 2 } ] }
3)、自定义分词器
request: POST _analyze { "tokenizer": "standard", "filter": ["lowercase"], "text":"Hello WORLD" } response: { "tokens": [ { "token": "hello", "start_offset": 0, "end_offset": 5, "type": "<ALPHANUM>", "position": 0 }, { "token": "world", "start_offset": 6, "end_offset": 11, "type": "<ALPHANUM>", "position": 1 } ] }
Elasticsearch自带的分词器
分词器(Analyzer) 特点 Standard(es默认) 支持多语言,按词切分并做小写处理 Simple 按照非字母切分,小写处理 Whitespace 按照空格来切分 Stop 去除语气助词,如the、an、的、这等 Keyword 不分词 Pattern 正则分词,默认\w+,即非字词符号做分割符 Language 常见语言的分词器(30+)
IK 实现中英文单词切分 自定义词库
不要直接下源码,不然还要打包编译,在release中下载,选择相匹配的版本;
https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v6.3.1
解压,将解压后的elasticsearch文件夹拷贝到/home/elk/elasticsearch/elasticsearch-6.3.1/plugins下下,并重命名文件夹为analysis-ik
重新启动ElasticSearch,即可加载IK分词器
IK提供了两个分词算法ik_smart 和 ik_max_word,其中 ik_smart 为最少切分,ik_max_word为最细粒度划分
1)最小切分:
POST _analyze { "analyzer": "ik_smart", "text":"php是世界上最好的语言" }
{ "tokens": [ { "token": "php", "start_offset": 0, "end_offset": 3, "type": "ENGLISH", "position": 0 }, { "token": "是", "start_offset": 3, "end_offset": 4, "type": "CN_CHAR", "position": 1 }, { "token": "世界上", "start_offset": 4, "end_offset": 7, "type": "CN_WORD", "position": 2 }, { "token": "最好", "start_offset": 7, "end_offset": 9, "type": "CN_WORD", "position": 3 }, { "token": "的", "start_offset": 9, "end_offset": 10, "type": "CN_CHAR", "position": 4 }, { "token": "语言", "start_offset": 10, "end_offset": 12, "type": "CN_WORD", "position": 5 } ] }
2)最细切分
POST _analyze { "analyzer": "ik_max_word", "text":"php是世界上最好的语言" }
{ "tokens": [ { "token": "php", "start_offset": 0, "end_offset": 3, "type": "ENGLISH", "position": 0 }, { "token": "是", "start_offset": 3, "end_offset": 4, "type": "CN_CHAR", "position": 1 }, { "token": "世界上", "start_offset": 4, "end_offset": 7, "type": "CN_WORD", "position": 2 }, { "token": "世界", "start_offset": 4, "end_offset": 6, "type": "CN_WORD", "position": 3 }, { "token": "上", "start_offset": 6, "end_offset": 7, "type": "CN_CHAR", "position": 4 }, { "token": "最好", "start_offset": 7, "end_offset": 9, "type": "CN_WORD", "position": 5 }, { "token": "的", "start_offset": 9, "end_offset": 10, "type": "CN_CHAR", "position": 6 }, { "token": "语言", "start_offset": 10, "end_offset": 12, "type": "CN_WORD", "position": 7 } ] }
世界上又分成了 世界 上,有重复的;
创建
文档通过其_index、_type、_id唯一确定
PUT /{index}/{type}/{id} { "field": "value", ... }
id不指定就会自动生成一个20位的_id;
更新直接PUT,version会发生变化;
局部更新:
pretty--格式化:
检索文档的一部分
GET /website/blog/123?_source=title,text
l 删除文档
删除文档的语法模式与之前基本一致,只不过要使用DELETE方法:
DELETE /website/blog/123
批量插入(从mysql中) | (每个json中不能有换行),先建立索引+doc,使用_bulk
POST test_search_index/doc/_bulk {"index":{"_id":1}} {"username":"alfred way","job":"java engineer","age":18,"birth":"1991-12-15","isMarried":false} {"index":{"_id":2}} {"username":"alfred","job":"java senior engineer and java specialist","age":28,"birth":"1980-05-07","isMarried":true} {"index":{"_id":3}} {"username":"lee","job":"java and ruby engineer","age":22,"birth":"1985-08-07","isMarried":false} {"index":{"_id":4}} {"username":"lee junior way","job":"ruby engineer","age":23,"birth":"1986-08-07","isMarried":false}
{ "took": 28, "errors": false, "items": [ { "index": { "_index": "test_search_index", "_type": "doc", "_id": "1", "_version": 3, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 2, "_primary_term": 1, "status": 200 } }, { "index": { "_index": "test_search_index", "_type": "doc", "_id": "2", "_version": 3, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 2, "_primary_term": 1, "status": 200 } }, { "index": { "_index": "test_search_index", "_type": "doc", "_id": "3", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1, "status": 201 } }, { "index": { "_index": "test_search_index", "_type": "doc", "_id": "4", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 3, "_primary_term": 1, "status": 201 } } ] }
原文:https://www.cnblogs.com/shengyang17/p/10583596.html