为啥要学ElasticSearch?---->搜索引擎
SQL:like查询,模糊搜索,那如果大数据量呢?—>编写索引—>分布式全文搜索引擎(百度、github、淘宝电商)
ElasticSearch是基于Lucene做了一些封装和增强(十分简单!!!)
Elasticsearch 是一个分布式、RESTful风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。 作为 Elastic Stack 的核心,它集中存储您的数据,帮助您发现意料之中以及意料之外的情况。
Elasticsearch 的底层是开源库 Lucene。但是,你没法直接用 Lucene,必须自己写代码去调用它的接口。Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。
ELK:Elasticsearch、Logstash、Kibana
特点:
采用Java开发,基于Luncene的全文搜索服务器,同时对其进行了扩展(扩展了面向抽象编程的地方,比如分词器,查询),提供了比Lucene更为丰富的查询语言(比如,过滤器),同时实现了可配置(跟hadoop整合,之前索引结构写在代码中,现在提前定义好)、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。
服务器 占用一个端口来提供服务 比如 可以加缓存
Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http G SolrJ操作提出查找请求(也可以提交json格式),并得到XML格式的返回结果。
Lucene是apache软件基金会的一个项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。
ElasticSearch优点:
ElasticSearch缺点:
==============================================================
Solr优点:
Solr缺点:
- 二者安装都很简单;
- Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
- Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
- Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
- Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch。
声明:JDK1.8以上—>最低要求
ES客户端,页面工具!----->基于java开发的和我们之后对应的java的核心jar包!版本对应!
先在windows下学习!
bin:启动文件
config:配置文件
jdk
lib 相关jar包
logs 日志
modules 功能模块
plugins 插件!
启动
双击bin目录下的.bat文件
安装可视化插件 head
发现问题:跨域问题。
可视化工具提供的端口是9100
而我们的ES则是9200,不互通
解决方法:在ES的配置文件中,修改跨域
http.cors.enabled: true
http.cors.allow-origin: "*"
网页测试:
这个head我们就理解成数据展示工具
我们后面所有的查询,可以去kibana去做
ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案,是三个产品的首字母缩写,分别是ElasticSearch、Logstash 和 Kibana。
ElasticSearch简称ES,它是一个实时的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。它是一个建立在全文搜索引擎 Apache Lucene 基础上的搜索引擎,使用 Java 语言编写。
Logstash是一个具有实时传输能力的数据收集引擎,用来进行数据收集(如:读取文本文件)、解析,并将数据发送给ES。
Kibana为 Elasticsearch 提供了分析和可视化的 Web 平台。它可以在 Elasticsearch 的索引中查找,交互数据,并生成各种维度表格、图形。
Kibana是一个开源的分析和可视化平台,设计用于和Elasticsearch一起工作。
你用Kibana来搜索,查看,并和存储在Elasticsearch索引中的数据进行交互。
你可以轻松地执行高级数据分析,并且以各种图标、表格和地图的形式可视化数据。
Kibana使得理解大量数据变得很容易。它简单的、基于浏览器的界面使你能够快速创建和共享动态仪表板,实时显示Elasticsearch查询的变化。
官网:https://www.elastic.co/cn/kibana
开发工具:
之后所有的操作都在这里进行编写!
集群,节点,索引,类型,文档,分片,映射是什么?
elasticsearch是面向文档,关系型数据库和elasticsearch客观的对比!一切都是json
Relational DB | Elasticsearch |
---|---|
数据库(database) | 索引(indices) |
表(tables) | types |
行(rows) | documents |
字段(columns) | fields |
物理设计:
elasticsearch在后台把每个索引划分成多个分片。每个分片可以在集群中的不同服务器间迁移
一个人就是一个集群!默认集群名就是elasticsearch
逻辑设计:
一个索引类型中,包含多个文档,当我们索引一篇文档时,可以通过这样的一个顺序找到它:索引-》类型-》文档id,通过这个组合我们就能索引到某个具体的文档。注意:ID不必是整数,实际上它是一个字符串。
文档
就是我们的一条条的记录
之前说elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档, elasticsearch中,文档有几个重要属性:
尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一一个年龄字段类型,可以是字符串也可以是整形。因为elasticsearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在elasticsearch中,类型有时候也称为映射类型。
类型
类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定 义称为映射,比如name映射为字符串类型。我们说文档是无模式的 ,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,那么elasticsearch是怎么做的呢?elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型, elasticsearch就开始猜,如果这个值是18 ,那么elasticsearch会认为它是整形。但是elasticsearch也可能猜不对 ,所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用,别整什么幺蛾子。
索引
就是数据库!
索引是映射类型的容器, elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。我们来研究下分片是如何工作的。
物理设计:节点和分片如何工作
一个集群至少有一 个节点,而一个节点就是一-个elasricsearch进程 ,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5个分片( primary shard ,又称主分片)构成的,每一个主分片会有-一个副本( replica shard ,又称复制分片)
上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同-个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。实际上, 一个分片是一个Lucene索引, -一个包含倒排索引的文件目录,倒排索引的结构使得elasticsearch在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。不过,等等,倒排索引是什么鬼?
倒排索引
elasticsearch使用的是一种称为倒排索引 |的结构,采用Lucene倒排索作为底层。这种结构适用于快速的全文搜索,一个索引由文
档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。 例如,现在有两个文档,每个文档包含如下内容
Study every day, good good up to forever # 文 档1包含的内容
To forever, study every day,good good up # 文档2包含的内容
为创建倒排索引,我们首先要将每个文档拆分成独立的词(或称为词条或者tokens) ,然后创建一一个包含所有不重 复的词条的排序列表,然后列出每个词条出现在哪个文档:
term | doc_1 | doc_2 |
---|---|---|
Study | √ | x |
To | x | x |
every | √ | √ |
forever | √ | √ |
day | √ | √ |
study | x | √ |
good | √ | √ |
every | √ | √ |
to | √ | x |
up | √ | √ |
现在,我们试图搜索 to forever,只需要查看包含每个词条的文档
term | doc_1 | doc_2 |
---|---|---|
to | √ | x |
forever | √ | √ |
total | 2 | 1 |
两个文档都匹配,但是第一个文档比第二个匹配程度更高。如果没有别的条件,现在,这两个包含关键字的文档都将返回。
再来看一个示例,比如我们通过博客标签来搜索博客文章。那么倒排索引列表就是这样的一个结构:
博客文章(原始数据) | 博客文章(原始数据) | 索引列表(倒排索引) | 索引列表(倒排索引) |
博客文章ID | 标签 | 标签 | 博客文章ID |
1 | python | python | 1,2,3 |
2 | python | linux | 3,4 |
3 | linux,python | ||
4 | linux |
如果要搜索含有python标签的文章,那相对于查找所有原始数据而言,查找倒排索引后的数据将会快的多。只需要查看标签这一栏,然后获取相关的文章ID即可。完全过滤掉无关的所有数据,提高效率!
elasticsearch的索引和Lucene的索引对比
在elasticsearch中,索引(库)这个词被频繁使用,这就是术语的使用。在elasticsearch中 ,索引被分为多个分片,每份分片是一个Lucene的索引。所以一个elasticsearch索引是由多 个Lucene索引组成的。别问为什么,谁让elasticsearch使用Lucene作为底层呢!如无特指,说起索引都是指elasticsearch的索引。
接下来的一切操作都在kibana中Dev Tools下的Console里完成。基础操作!
1.索引(数据库)
2.字段类型(可以理解为映射mapping)
3.文档(数据)
4.采用分片的方式
什么是IK分词器?
分词:即是把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每一个字看成一个词,比如“我爱吃饭”---->会被分词“我”,“爱”,“吃”,“饭”,这显然是不符合要求的,所以我们需要安装中文分词器ik解决此问题
#ik提供了两种分词算法
ik_smart #最少切分
ik_max_word #最细粒度划分
安装
下载完毕之后,放入到es插件中即可
重启观察:
命令行测试:
使用Kibana测试:
思考:当我们输入一些其他词汇时,可能会被拆开,不是我们想得到的,怎么办呢?
这种我们自己需要的词,需要我们自己加到我们的分词器的字典中
一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
method | url地址 | 描述 |
---|---|---|
PUT | localhost:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST | localhost:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST | localhost:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE | localhost:9200/索引名称/类型名称/文档id | 删除文档 |
GET | localhost:9200/索引名称/类型名称/文档id | 通过文档id查询文档 |
POST | localhost:9200/索引名称/类型名称/_search | 查询所有的数据 |
1.在kibana创建一个索引
PUT /索引名/类型名/文档id
2.在head中查看
3.数据浏览:
完成了自动添加索引!!!数据也成功的添加了!
扩展:字段指定类型
具体使用可以查看官方文档!
4.指定类型
PUT /test2
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age" : {
"type": "long"
},
"birthday": {
"type": "date"
}
}
}
}
获得索引信息:
查看默认信息:
如果我们的文档没有指定字段类型,那么我们的es就会自动匹配
扩展:cat命令
GET _cat/
indices?v 查看es相关信息
添加数据
PUT /nba/user/1
{
"name": "乔治",
"age": 31,
"desc": "快船大核",
"tags": ["三分","钓鱼","扣篮"]
}
获取数据
GET nba/user/1
POST /nba/user/3/_update
{
"doc": {
"age": 37
}
}
简单条件搜索
GET nba/user/_search?q=name:乔治
GET nba/user/_search
{
"query": {
"match": {
"name": "勒布朗"
}
}
}
进阶查询
GET nba/user/_search
{
"query": {
"match": {
"name": "布朗"
}
}
}
指定字段查询
GET nba/user/_search
{
"query": {
"match": {
"name": "布朗"
}
},
"_source": ["name","desc"]
}
我们之后使用java操作es,所有的方法和对象局输这里面的key!
排序
GET nba/user/_search
{
"sort": [
{
"age": {
"order": "desc"
}
}
],
"_source": ["name","age"]
}
分页查询
GET nba/user/_search
{
"sort": [
{
"age": {
"order": "desc"
}
}
],
"_source": ["name","age"],
"from": 0,
"size": 2
}
布尔值查询
must (and),所有的条件都要符合
GET nba/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"age": 24
}
}
]
}
}
}
GET nba/user/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"age": 24
}
},
{
"match": {
"name": "勒布朗"
}
}
]
}
}
}
GET nba/user/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"age": 24
}
}
]
}
}
}
过滤器filter
GET nba/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "布朗"
}
}
],
"filter": {
"range": {
"age": {
"gt": 30,
"lt": 40
}
}
}
}
}
}
匹配多个搜索条件
GET nba/user/_search
{
"query": {
"match": {
"tags": "人 中"
}
}
}
精确查询
term 查询是直接通过倒排索引指定的词条进行精确的查找
关于分词:
term,直接查找精确的值
match,会使用分词器解析(分析文档在查询)
两个类型:
text:text类型可以被分词器解析
key-word:不能被分词器解析,整个词
// 建一个索引,并指定类型
PUT testdb
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"desc":{
"type": "keyword"
}
}
}
}
//添加一条数据
PUT testdb/_doc/1
{
"name": "zjdzka 编程",
"desc": "zjdzka 学习"
}
PUT testdb/_doc/1
{
"name": "zjdzka 编程",
"desc": "zjdzka 学习2"
}
//查询,采用keyword
GET _analyze
{
"analyzer": "keyword",
"text": "zjdzka 编程"
}
//查询,采用分词器
GET _analyze
{
"analyzer": "standard",
"text": "zjdzka 编程"
}
精确term案例
GET testdb/_search
{
"query": {
"term": {
"desc": "zjdzka 学习"
}
}
}
总结:因为desc字段采用的是keyword类型,所以zjdzka 学习
和zjdzka 学习2
被识别为两个词汇,因此查询只能查出一个
多个值匹配的精确查询
PUT testdb/_doc/5
{
"t1": "哈哈哈",
"t2": "22"
}
PUT testdb/_doc/6
{
"t1": "嘻嘻嘻",
"t2": "33"
}
//查询
GET testdb/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"t2": "22"
}
},
{
"term": {
"t2": "33"
}
}
]
}
}
}
高亮查询
GET nba/user/_search
{
"query": {
"match": {
"name": "乔治"
}
},
"highlight": {
"fields": {
"name": {
}
}
}
}
//自定义高亮
GET nba/user/_search
{
"query": {
"match": {
"name": "乔治"
}
},
"highlight": {
"pre_tags": ""
,
"post_tags": "",
"fields": {
"name": {
}
}
}
}
其实Mysql也可以实现,只是ES效率更高效