1 认识ElasticSearch
1.1 为什么要使用ElasticSearch
实际项目中,我们建立一个网站或应用程序,并要添加搜索功能,令我们受打击的是:搜索工作是很难的。我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON/XML通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并在需要扩容时方便地扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。<br /> 虽然全文搜索领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene的配置及使用非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
1.2 ElasticSearch(简称ES)
ES即为了解决原生Lucene使用的不足,优化Lucene的调用方式,并实现了高可用的分布式集群的搜索方案,其第一个版本于2010年2月出现在GitHub上并迅速成为最受欢迎的项目之一。<br /> 首先,ES的索引库管理支持依然是基于Apache Lucene(TM)的开源搜索引擎。ES也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。Lucene直接通过java API调用,而ES把这些API调用过程进行了的封装为简单RESTful请求,让我们调用起来更加简单.<br /> 不过,ES的核心不在于Lucene,其特点更多的体现为:分布式的实时文件存储,每个字段都被索引并可被搜索,分布式的实时分析搜索引擎,可以扩展到上百台服务器,处理PB级结构化或非结构化数据,高度集成化的服务,你的应用可以通过简单的 RESTful API、各种语言的客户端甚至命令行与之交互。上手Elasticsearch非常容易。它提供了许多合理的缺省值,并对初学者隐藏了复杂的搜索引擎理论。它拥有开瓶即饮的效果(安装即可使用),只需很少的学习既可在生产环境中使用。<br /> Lucene和ES联系,区别:项目中为啥使用ES而不用Lucene.<br /> 联系:ElasticSearch封装了Lucene,让使用变得更简单,在高可用上面做得更好。<br /> 区别:ElasticSearch除了拥有Lucene所有优点以外,还拥有自己优点.<br /> 可用性:支持集群没有单点故障<br /> 扩展性:支持集群扩展<br /> 一般lucene在中小型项目中使用(但是也能使用es),而ES在大型项目中使用.因为ES支持在集群环境使用,并且自身也支持集群.
2 ES安装及使用说明
3 Restful认识
Restful是一种面向资源的架构风格,可以简单理解为:使用URL定位资源,用HTTP动词(GET,POST,DELETE,PUT)描述操作。 url中不要出现动词。
GET查询
PUT添加
POST修改
DELE删除
用户做crud
Get http://localhost:8080/employee/1
Get http://localhost:8080/employees
put http://localhost:8080/employee
{
“name”:”zs”,
“age”:17
}
delete http://localhost:8080/employee/1
Post http://localhost:8080/employee/1
{
}
使用Restful的好处:
透明性,暴露资源存在。
充分利用 HTTP 协议本身语义。
无状态,这点非常重要。在调用一个接口(interface)(访问、操作资源)的时候,可以不用考虑上下文,不用考虑当前状态,极大的降低了复杂度。
HTTP 本身提供了丰富的内容协商手段,无论是缓存,还是资源修改的乐观并发控制,都可以以业务无关的中间件来实现。
Restful的典型特征:
① Server(controller)提供的RESTful API(requestMapping(“/deleteUserById/{id}”)中,URL中只使用名词来指定资源。
getUserById
“资源”是REST架构或者说整个网络处理的核心。比如:
GET http://api.woniu.cn/emp/323: 获取323号员工的基本资料;
@RequstMapping(“/emp/{id}”,method=Me.GET)
Public AjaxResult getUserById(@PathVavirli(“id”) Long id){
//sdfsfsd
}
Delete http://api.woniu.cn/emp/323: 删除一个323的员工
@RequstMapping(“/emp/{id}”,method=Me.DELETE)
Public AjaxResult delete(@PathVavirli(“id”) Long id){
//sdfsfsd
}
GET http://api.woniu.cn/emps: 获取所有员工资料列表;
② REST 是面向资源的,这个概念非常重要,而资源是通过 URI 进行暴露
URI 的设计只要负责把资源通过合理方式暴露出来就可以了。对资源的操作与它无关,所以REST 通过 URI 暴露资源时,会强调不要在 URI 中出现动词。
比如:左边是错误的设计,而右边是正确的
GET /rest/api/getDogs -> GET /rest/api/dogs 获取所有小狗狗
GET /rest/api/addDogs -> PUT/rest/api/dogs 添加一个小狗狗
POST /rest/api/editDogs/12 -> POST /rest/api/dogs/12 修改一个小狗狗
POST /rest/api/deleteDogs/12 -> DELETE /rest/api/dogs/12 删除一个小狗狗
左边的这种设计,很明显不符合REST风格,URI 只负责准确无误的暴露资源,而 getDogs/addDogs…已经包含了对资源的操作,这是不对的。相反右边却满足了,它的操作是使用标准的HTTP动词来体现。
③ 用HTTP协议里的动词来实现资源的添加,修改,删除等操作。
即通过HTTP动词来实现资源的状态扭转:
GET 用来获取资源,
POST 用来新建资源(也可以用于更新资源),
PUT 用来更新资源,
DELETE 用来删除资源。
比如:
GET http://api.woniu.cn/emp/323
PUT http://api.woniu.cn/emp: 添加一个员工
POST http://api.woniu.cn/emp/232: 更新232号员工资料
DELETE http://api.woniu.cn/emp/323: 删除323号员工
4 ES数据管理
4.1 什么是ES中的文档
ES是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index,创建索引)每个文档的内容使之可以被搜索。在ES中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。
ES使用Javascript对象符号(JavaScript Object Notation),也就是JSON,作为文档序列化格式。JSON现在已经被大多语言所支持,而且已经成为NoSQL领域的标准格式。
ES存储的一个员工文档的格式示例:
{
“email”: “wb@woniu.com”,
“name”: “文兵”,
“info”: {
“addr”: “四川省成都市”,
“age”: 30,
“interests”: [ “樱桃”, “粉嫩” ]
},
“join_date”: “2014-06-01”
}
尽管原始的 employee对象很复杂,但它的结构和对象的含义已经被完整的体现在JSON中了,在ES中将对象转化为JSON并做索引要比在表结构中做相同的事情简单的多。
一个文档不只有数据。它还包含元数据(metadata)—关于文档的信息。三个必须的元数据节点是:
节点 | 说明 |
---|---|
_index | 索引库,文档存储的地方 |
_type | 文档类型(6.x之后取消掉了这个属性) |
_id | 文档的唯一标识 |
_index:索引库,类似于关系型数据库里的“数据库”—它是我们存储和索引关联数据的地方。
_type:类型,类似于关系型数据库中表.在应用中,我们使用对象表示一些“事物”,例如一个用户、一篇博客、一个评论,或者一封邮件。可以是大写或小写,不能包含下划线或逗号。我们将使用 employee 做为类型名。
_id: 与 _index 和 _type 组合时,就可以在ELasticsearch中唯一标识一个文档。当创建一个文档,你可以自定义 _id ,也可以让Elasticsearch帮你自动生成。
另外还包括:_uid 文档唯一标识(_type#_id)
_source:文档原始数据
_all:所有字段的连接字符串
4.2 文档的增删改
我们以员工对象为例,我们首先要做的是存储员工数据,每个文档代表一个员工。在ES中存储数据的行为就叫做索引(indexing),文档归属于一种类型(type),而这些类型存在于索引(index)中,我们可以简单的对比传统数据库和ES的对应关系:<br />关系数据库(MYSQL) -> 数据库DB-> 表TABLE-> 行ROW-> 列Column<br />Elasticsearch -> 索引库Indices -> 类型Types -> 文档Documents -> 字段Fields<br />ES集群可以包含多个索引(indices)(数据库),每一个索引库中可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。<br />**_创建索引文档_**
使用自己的ID创建
PUT {index}/{type}/{id} { "field": "value", ... }
使用内置ID创建
POST {index}/{type} { "field": "value", ... }
获取指定ID的文档
GET itsource/employee/123
更新文档
PUT {index}/{type}/{id} { "field": "value", ... }
跟创建语法一样,但是会改变版本号
删除文档
DELETE {index}/{type}/{id}
注意:尽管文档不存在,但_version依旧增加了。这是内部记录的一部分,它确保在多节点间不同操作可以有正确的顺序
4.3 文档的简单查询(searchAPI)
GET /_search GET /woniu47/_search GET /woniu47,woniu48/_search GET /woniu*/_search
URLsearch:
通过ID获取GET /woniu47/_doc/1
只返回文档内容,不要元数据:
GET /woniu47/_doc/1/_source
查询字符串搜索:
返回文档的部分字段:GET /woniu47/_doc/1?_source=name,age
查询年龄为25岁的学员
GET /woniu47/_search?q=age:25
组合查询:
组合查询:
+表示并且,多个条件做且运算====>MUST
空格表示或,多个条件做或运算====>SHOULD
-表示非,多个条件做非运算====>MUST_NOT
+name:john +tweet:mary
+name:(mary john) +date:>2014-09-10 +(aggregations geo)
age[20 TO 30]
查询年龄在25到28 (两边都包括)或则姓名为wangwu的学员GET /woniu47/_search?q=age:>=25 +age<=28 name:wangwu
GET /woniu47/_search?q=age[25 TO 28] name:wangwu
中括号可以换成大括号,中括号有=大括号没有
分页:
查询20岁以上的学员,显示3条GET /woniu47/_search?q=age:>=20&size=3
查询20岁以上的学员,每页显示3条,显示第2页
GET /woniu47/_search?q=age:>=20&size=3&from=3
查询参数说明:
Name | Description |
---|---|
q | 标识查询字符串 |
df | 在查询中,没有定义字段前缀的情况下默认字段的前缀 |
analyzer | 在分析查询字符串时,分析器的名字 |
default_operator | 被用到的默认操作,有AND和OR两种,默认是OR |
explain | 对于每一个命中,对怎样得到命中得分的计算给出一个解释 |
_source | 将其设置为false,查询就会放弃检索_source字段。也可以通过设置检索部分文档 |
fields | 命中的文档返回的字段 |
sort | 排序执行,可以fieldName、fieldName:asc |
track_scores | 当排序的时候,将其设置为true,可以返回相关度得分 |
from | 分页查询起始点,默认0 |
size | 查询数量,默认10 |
search_type | 搜索操作执行的类型 |
…… | …… |