REST : 表现层状态转化(Representational State Transfer),如果一个架构符合REST原则,就称它为RESTful 架构风格。
资源: 所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。
表现层 :我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。
状态转化(State Transfer):如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(StateTransfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
REST原则:
1.一个URL代表一个唯一资源。传统的URL比如说:http://localhost:8989/user/findOne?id=21,这里的?id=21并不是URL的一部分,而是携带的参数。前面的http://localhost:8989/user/findOne并不能代表一个唯一资源。
2.并且通过HTTP协议里面四个动词:GET、POST、PUT、DELETE对应四种服务器端的基本操作:GET用来查询资源,POST用来添加资源(也可以用于更新资源),PUT用来更新或者添加资源,DELETE用来删除资源。
全文检索是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程。
检索: 索(建立索引) 检:(检索索引)
全文检索(Full-Text Retrieval(检索))以文本作为检索对象,找出含有指定词汇的文本。全面、准确和快速是衡量全文检索系统的关键指标。
关于全文检索,我们要知道:
ElasticSearch 简称 ES ,是基于Apache Lucene构建的开源搜索引擎,是当前流行的企业级搜索引擎。Lucene本身就可以被认为迄今为止性能最好的一款开源搜索引擎工具包,但是lucene的API相对复杂,需要深厚的搜索理论。很难集成到实际的应用中去。但是ES是采用java语言编写,提供了简单易用的RestFul API,开发者可以使用其简单的RestFul API,开发相关的搜索功能,从而避免lucene的复杂性。
ES主要以轻量级JSON作为数据存储格式,这点与MongoDB有点类似,但它在读写性能上优于 MongoDB 。同时也支持地理位置查询,还方便地理位置和文本混合查询。以及在统计、日志类数据存储和分析、可视化这方面是引领者。
国外:Wikipedia(维基百科)使用ES提供全文搜索并高亮关键字、StackOverflow(IT问答网站)结合全文搜索与地理位置查询、Github使用Elasticsearch检索1300亿行的代码。
国内:百度(在云分析、网盟、预测、文库、钱包、风控等业务上都应用了ES,单集群每天导入30TB+数据, 总共每天60TB+)、新浪、阿里巴巴、腾讯等公司均有对ES的使用。
使用比较广泛的平台ELK(ElasticSearch, Logstash, Kibana)。
本次安装所需要的环境
centos7 +
java 8 +
elasticserch 6.8.0 +
(1)JDK 安装:
详细安装步骤参考:Linux安装JDK
(2)ElasticSearch 安装
注: ES不能以root用户身份安装,必须创建普通用户
# a.在linux系统中创建新的组
groupadd es
# b.创建新的用户es并将es用户放入es组中
useradd es -g es
# c.修改es用户密码
passwd es
然后以es用户登录虚拟机,查看当前用户身份:
who am i
下面正式进入安装阶段。
1.解压缩 elasticsearch
tar -zxvf elasticsearch-6.8.0.tar.gz
2.进入bin目录中启动ES服务
./elasticsearch
出现下图红色日志说明启动成功:
3.测试
es提供了两个接口,一个是web直接访问的端口,另外一个是使用java等程序可以调用的接口,在这里我们用9200接口进行测试。
Q:为什么不能用浏览器访问?
A:es启动之后,不提供任何远程连接,只能本地访问。
Q:为什么我只在一台机器上启动了es,却显示集群的相关信息呢?
A:es中,一台机器也算是集群。
curl 是 Linux 中用来模拟浏览器发送请求的命令
curl http://localhost:9200
若出现下图,则表示成功。
至此,ElasticSearch 安装基本完成!
注意:ES服务默认启动是受保护的,只允许本地客户端连接,如果想要通过远程客户端访问,必须开启远程连接
(1)开启ES远程访问
vim elasticsearch.yml
network.host: 0.0.0.0 #将原来network修改为此配置
(2)重启启动ES服务
./elasticsearch
重新启动es出现如下错误:
(3)解决错误
错误1解决:
使用root用户修改系统配置
vim /etc/security/limits.conf
在最后面追加下面内容(注意星号要顶格写)
* soft nofile 65536
* hard nofile 65536
* soft nproc 4096
* hard nproc 4096
重新登录之后检测配置是否生效
ulimit -Hn
ulimit -Sn
ulimit -Hu
ulimit -Su
错误2解决:
使用root用户修改系统配置
vim /etc/security/limits.d/20-nproc.conf
将红圈名字修改为启动es的普通用户名。
错误3解决:
使用root用户修改系统配置
vim /etc/sysctl.conf
# 末尾添加
vm.max_map_count=655360
# 执行如下命令检测是否生效
sysctl -p
(4)重新连接启动服务
发现es可以正常启动了
./elasticsearch
(1)接近实时(NRT Near Real Time )
Elasticsearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒内)
(2)索引(index)
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。索引类似于关系型数据库中Database的概念。在一个集群中,如果你想,可以定义任意多的索引。
(3)类型(type)
在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。类型类似于关系型数据库中Table的概念。
NOTE: 在5.x版本以前可以在一个索引中定义多个类型,6.x之后版本也可以使用,但是不推荐,在7~8.x版本中彻底移除一个索引中创建多个类型
(4)映射(Mapping)
Mapping是ES中的一个很重要的内容,它类似于传统关系型数据中table的schema,用于定义一个索引(index)中的类型(type)的数据的结构。 在ES中,我们可以手动创建type(相当于table)和mapping(相关与schema),也可以采用默认创建方式。在默认配置下,ES可以根据插入的数据自动地创建type及其mapping。 mapping中主要包括字段名、字段数据类型和字段索引类型。
(5)文档(document)
一个文档是一个可被索引的基础信息单元,类似于表中的一条记录。比如,你可以拥有某一个员工的文档,也可以拥有某个商品的一个文档。文档以采用了轻量级的数据交换格式JSON(Javascript Object Notation)来表示。
Kibana是一个针对Elasticsearch的开源分析及可视化平台,使用Kibana可以查询、查看并与存储在ES索引的数据进行交互操作,使用Kibana能执行高级的数据分析,并能以图表、表格和地图的形式查看数据。
kibana的版本一定要与ElasticSearch的版本对应!
官网下载地址:https://www.elastic.co/cn/downloads/kibana
(1)下载Kibana成功后进行安装
rpm -ivh kibana-6.8.0-x86_64.rpm
(2)编辑配置文件
cd kibana-6.8.0-linux-x86_64/config
vim kibana.yml
修改成如下配置:
# 找到之后并修改成如下配置
server.host: "192.168.40.151" # ES服务器主机地址
elasticsearch.hosts: ["http://192.168.40.151:9200"] # ES服务器地址
(3)启动kibana
如果和本文一样是通过rpm安装的,则输入以下代码即可启动。
systemctl start kibana
(4)访问kibana
5601为kibana的默认端口,浏览器访问http://192.168.40.151:5601即可查看到kibana界面。
上一步我们安装好了kibana,我们可以使用客户端kibana直接操作ElasticSearch。
# 创建索引
PUT /dangdang/
# 删除索引
DELETE /dangdang
# 删除所有索引[慎用:ElasticSearch会自带两个索引,如果删除kibana客户端将不能使用,只有重启kibana后才能使用]
DELETE /*
# 查看索引信息
GET /_cat/indices
# 查看索引信息和表头信息
GET /_cat/indices?v
注意: 这种方式创建类型要求索引不能存在
# 创建/book索引并创建(musicbook)类型
PUT /book
{
"mappings": {
"musicbook": {
"properties": {
"name":{
"type":"keyword"
},
"price":{
"type":"double"
},
"desc":{
"type":"text"
}
}
}
}
}
# 语法
GET /索引名/_mapping
# 比如
GET /book/_mapping
/book:即我们创建的索引名字
“mappimgs”:映射,固定写法,即对类型的数据结构进行约束,这样在添加文档时,就会有约束
“musicbook”:即类型名,ES6之后建议一个索引创建一个类型
“properties”:属性,固定写法,即将类型所要创建的属性添加在里面
“name”…等:属性名
“type”:固定写法,约束类型,可以根据属性的不同写不同类型
Mapping Type: text , keyword , date ,integer, long , double , boolean or ip
# 添加文档:语法 PUT /索引/类型/id
# 如果不指定id,ES默认会生成一个_id,后面操作文档都根据此_id。
# 这也是为什么在给类型添加属性时,一般不添加id属性。
PUT /book/musicbook/1
{
"name":"音乐书",
"price":"22.0",
"desc":"这是一本音乐书"
}
返回结果:
{
"_index" : "book",
"_type" : "musicBook",
"_id" : "1",
"_version" : 3,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
# 查询文档:语法 GET /索引/类型/id
GET /book/musicbook/1
返回结果:
{
"_index" : "book",
"_type" : "musicBook",
"_id" : "1",
"_version" : 3,
"_seq_no" : 2,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "音乐书",
"price" : "22.0",
"desc" : "这是一本音乐书"
}
}
# 删除文档:语法 DELETE /索引/类型/id
DELETE /book/musicbook/1
返回结果:
{
"_index" : "book",
"_type" : "musicBook",
"_id" : "1",
"_version" : 4,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 3,
"_primary_term" : 1
}
# 更新文档
# 错误方式
POST /book/musicbook/1
{
"name":"张三"
}
# 查看文档之后发现,覆盖掉了原有的属性信息,只有新更新的
{
"_index" : "book",
"_type" : "musicBook",
"_id" : "1",
"_version" : 2,
"_seq_no" : 5,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "张三"
}
}
# 正确方式: 使用关键词_update
POST /索引/类型/id/_update
{
"doc":{
"属性名":"值"
}
}
# 方式一:在原有数据基础上进行更新
POST /book/musicbook/1/_update
{
"doc": {
"price":"40"
}
}
# 第二种方式:添加新的约束的数据
这种方式,type并没有color属性,但你添加的时候,ES会给你进行相应的匹配
POST /book/musicbook/1/_update
{
"doc": {
"color":"红色"
}
}
# 第三种方式:根据script脚本进行更新[了解]
POST /book/musicbook/1/_update
{
"script": "ctx._source.price += 5.0"
}
有时候,想要同时添加文档、删除文档、修改文档、索引文档组合进行,使用关键词 _bulk。
注意:所谓批量操作,简单说就是你想进行删除操作,你就使用"delete"关键词,想要进行修改操作,你就使用"update"关键词。批量时不会因为一个失败而全部失败,而是继续执行后续操作,批量在返回时按照执行的状态开始返回。
# 同时索引两个文档
PUT /book/musicbook/_bulk
{"index":{"_id": "3"}}
{ "name":"童话书", "price":"21","des":"这是一本童话书"}
{"index":{"_id": "4"}}
{"name":"冒险书","price":"24","desc":"这是一本冒险书"}
# 同时修改和删除文档
PUT /book/musicbook/_bulk
{"update":{"_id":"3"}}
{"doc":{"name":"修改后的童话书"}}
{"delete":{"_id":"4"}}
ES官方提供了两中检索方式:一种是通过 URL 参数进行搜索,另一种是通过 DSL(Domain Specified Language) 进行搜索。官方更推荐使用第二种方式。因为第二种方式是基于传递JSON作为请求体(request body)格式与ES进行交互,这种方式更强大,更简洁。
语法:
URL查询: GET /索引/类型/_search?参数
DSL查询: GET /索引/类型/_search {}
第一种使用较少,了解即可!
测试数据
# 1.删除索引
DELETE /ems
# 2.创建索引并指定类型
PUT /ems
{
"mappings":{
"emp":{
"properties":{
"name":{
"type":"text"
},
"age":{
"type":"integer"
},
"bir":{
"type":"date"
},
"content":{
"type":"text"
},
"address":{
"type":"keyword"
}
}
}
}
}
# 3.插入测试数据
PUT /ems/emp/_bulk
{"index":{}}
{"name":"小黑","age":23,"bir":"2012-12-12","content":"为开发团队选择一款优秀的MVC框架是件难事儿,在众多可行的方案中决择需要很高的经验和水平","address":"北京"}
{"index":{}}
{"name":"王小黑","age":24,"bir":"2012-12-12","content":"Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式","address":"上海"}
{"index":{}}
{"name":"张小五","age":8,"bir":"2012-12-12","content":"Spring Cloud 作为Java 语言的微服务框架,它依赖于Spring Boot,有快速开发、持续交付和容易部署等特点。Spring Cloud 的组件非常多,涉及微服务的方方面面,井在开源社区Spring 和Netflix 、Pivotal 两大公司的推动下越来越完善","address":"无锡"}
{"index":{}}
{"name":"win7","age":9,"bir":"2012-12-12","content":"Spring的目标是致力于全方位的简化Java开发。 这势必引出更多的解释, Spring是如何简化Java开发的?","address":"南京"}
{"index":{}}
{"name":"梅超风","age":43,"bir":"2012-12-12","content":"Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API","address":"杭州"}
{"index":{}}
{"name":"张无忌","age":59,"bir":"2012-12-12","content":"ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口","address":"北京"}
NOTE:了解即可,有助于更好了解DSL
GET /ems/emp/_search?q=*&sort=age:desc&size=5&from=0&_source=name,age,bir
_search:搜索的API
q=* :匹配所有文档
sort=age:按照指定字段进行排序,默认为升序,:desc 降序排列
size:展示多少条数据
from:展示第几页
_source:只匹配哪些字段
(1)查询所有(match_all)
match_all关键字: 返回索引中的全部文档
GET /ems/emp/_search
{
"query": {
"match_all": {}
}
}
(2)查询结果中返回指定条数(size)
size 关键字: 指定查询结果中返回指定条数。默认返回值10条,这是对查询的结果进行处理。
GET /ems/emp/_search
{
"query": {
"match_all": {}
},
"size": 5
}
(3)分页查询(from)
from 关键字: 用来指定起始返回位置,和size关键字连用可实现分页效果
GET /ems/emp/_search
{
"query": {
"match_all": {}
},
"size": 5,
"from": 0
}
(4)查询结果中返回指定字段(_source)
_source 关键字: 是一个数组,在数组中用来指定展示那些字段
# 展示单个字段
GET /ems/emp/_search
{
"query": {
"match_all": {}
},
"_source": "name"
}
# 展示多个字段
GET /ems/emp/_search
{
"query": {
"match_all": {}
},
"_source": ["name","age"]
}
(5)关键词查询(term)
term 关键字: 用来使用关键词查询
# name 是text类型,会进行分词,所以name包含“张”的文档都行
GET /ems/emp/_search
{
"query": {
"term": {
"name": {
"value": "张"
}
}
}
}
# bir 是date类型,不会进行分词,所以按照整体查询,查不到数据
GET /ems/emp/_search
{
"query": {
"term": {
"bir": {
"value": "2012-12"
}
}
}
}
总结:
NOTE1:
通过使用term查询得知ES中默认使用分词器为标准分词(StandardAnalyzer),标准分词器对于英文单词分词,对于中文单字分词。NOTE2:
通过使用term查询得知,在ES的Mapping Type中keyword, date,integer, long,double, boolean or ip 这些类型不分词,只有text类型分词。