es 官网: www.elastic.co
1. Elasticsearch 简介
Elasticsearch是一个基于Apache Lucene™的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。
2. Elasticsearch 特点
分布式的实时文件存储,每个字段都被索引并可被搜索
分布式的实时分析搜索引擎
可以扩展到上百台服务器,处理PB级结构化或非结构化数据
3. Elasticsearch 作用
全文检索(全部字段)、模糊查询(搜索)、数据分析(提供分析语法,例如聚合)当然也可以保存数据
4. Elasticsearch 和 solr 比较
(1).Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
(2).Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
(3).Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供
;
(4).Solr 在传统的搜索应用中表现好于 Elasticsearch,
但在处理实时搜索应用时效率明显低于 Elasticsearch,例如微信附近的人功能就是es 实现的;
(5).es 可以通过RESTful API 做到对数据的增删改(http 请求对数据操作);
5. Elasticsearch 使用案例
GitHub:2013年初,GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使用ElasticSearch搜索20TB的数据,包括13亿文件和1300亿行代码”
百度:百度目前广泛使用ElasticSearch作为文本数据分析,
6. Elasticsearch 的安装
安装细节步骤见如下博客
7. Elasticsearch的交互方式
(1).基于HTTP协议,以JSON为数据交互格式的RESTful API
GET POST PUT DELETE HEAD
这里浏览器默认是get 请求,也可以使用谷歌的插件postman实现其他RESTful 方法测试
(2).Elasticsearch官方提供了多种程序语言的客户端—java,Javascript,.NET,PHP,Perl,Python,以及 Ruby——还有很多由社区提供的客户端和插件
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.3/java-rest-high-getting-started-maven.html
(3). Kibana的Dev Tools,kibana与es是一系列产品,版本号要一样
(4) linux命令行,主要使用curl 命令,
linux curl 命令:http命令行工具
Ps:由于安装linux的时候很多时候是没有安装桌面的,也意味着没有浏览器,因此这个方法也经常用于测试一台服务器是否可以到达一个网站
root@hadoop-01 ~]# curl 192.168.23.201:9200
{
"name" : "CGJRcPd",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "nQYvkIXCQTCiiB6Q0ht_aA",
"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"
}
8. Elasticsearch数据存储方式
es 保存数据的时候,会把数据先分词,分词结果建立索引,存储在索引库中,然后数据内容保存在文档区
(1).面向文档
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。
以下对比mysql 和 es:
mysql 存储单元是二维表 一类数据保存为一张表 mysql 有很多二维表
es存储单元是 一个文档 一条数据一个文档 es 有很多文档 文档中是以json形式保存
(2).JSON
ELasticsearch使用Javascript对象符号(JavaScript Object Notation),也就是JSON,作为文档序列化格式。JSON现在已经被大多语言所支持,而且已经成为NoSQL领域的标准格式。它简洁、简单且容易阅读。字符串+字节码可以通过java不序列传输
小结:es 数据的格式就是json
一条数据就是一个文档
9. Elasticsearch存储结构
(1)元数据
创建文档语句
PUTguigu/doc/1
{
“name”:”zhangsan”,
“age”:10
}
respose
{
"_index": "guigu",
"_type": "doc",
"_id": "1",
"_version": 3,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1
}
_index:文档所在索引名称
_type:文档所在类型名称
_id:文档唯一id
_uid:组合id,由_type和_id组成(6.x后,_type不再起作用,同_id)
_source:文档的原始Json数据,包括每个字段的内容
_all:将所有字段内容整合起来,默认禁用(用于对所有字段内容检索)
(2)名词解释
a. 索引 index
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。
b. 类型 type
Es6之后,一个index中只能有一个type
在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中,你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。
c. 字段Field
相当于是数据表的字段,对文档数据根据不同属性进行的分类标识
d. document
一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。
(3) es 对比 mysql 名词对比
es | mysql |
index | database |
type(_doc) | table |
document | 表 |
es 6.X 版本之后弱化了type ,一个index只有一个type,type名称为_doc
10. Elasticsearch检索
(1).检索文档
Mysql : select * from user where id = 1
格式: GET /index/type/id
举例:
ES : GET /atguigu/doc/1
结果:
{
"_index": "atguigu",
"_type": "doc",
"_id": "1",
"_version": 3,
"found": true,
"_source": {
"name": "zhangsan",
"age": 10
}
}
(2).简单检索
Mysql : select * from user
格式 GET /index/type/_search
举例
ES : GET /atguigu/doc/_search
{
"took": 73,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "atguigu",
"_type": "doc",
"_id": "2",
"_score": 1,
"_source": {
"name": "zhangsan",
"age": 10
}
},
{
"_index": "atguigu",
"_type": "doc",
"_id": "1",
"_score": 1,
"_source": {
"name": "zhangsan",
"age": 10
}
}
]
}
}
(3).全文检索
格式:GET /index/type/_search?q=“检索词”
ES : GET /megacorp/employee/_search?q=haha
查询出所有文档字段值为haha的文档
(4).搜索(模糊查询)
格式:GET /index/type/_search?q=“检索词”
ES : GET /megacorp/employee/_search?q=hello
查询出所有文档字段值分词后包含hello的文档
(5).聚合
类似mysql 的group by
Elasticsearch有一个功能叫做聚合(aggregations),它允许你在数据上生成复杂的分析统计。它很像SQL中的GROUP BY但是功能更强大。
举个例子,让我们找到所有职员中最大的共同点(兴趣爱好)是什么:
GET /atguigu/doc/_search
{
"aggs": {
"all_interests": {
"terms": { "field": "interests" }
}
}
}
结果
{
...
"hits": { ... },
"aggregations": {
"all_interests": {
"buckets": [
{
"key": "music",
"doc_count": 2
},
{
"key": "forestry",
"doc_count": 1
},
{
"key": "sports",
"doc_count": 1
}
]
}
}
}
11. Elasticsearch搜索原理
搜索原理总结:
输入关键字搜素---->es 引擎对关键字分词---->每个网站都对应一个倒排索引库(倒排索引库底内存结构是b+tree) + Posting List—>根据分词的词汇 在倒排索引库中 查出索引—>根据索引查出文章内容
倒排索引库(根据硅谷字段查询id)<-----百度维护搜素资源库(url logo contenxt tittle …)<–爬虫万维网
搜索框—>搜索关键字 ”尚硅谷培训机构”—>分词 尚硅谷 硅谷 …>到百度倒排索引区索引---->查询得到id
(1).正排索引:记录文档Id到文档内容、单词的关联关系
根据id—>查询内容
docid | content |
1 | 尚硅谷,是,最好的,培训,机构 |
2 | php是世界上最好的语言 |
(2).倒排索引:记录单词到文档id的关联关系,
类似mysql根据内容—> 查询id
倒排索引包含:
单词词典(Term DicTionary):记录所有文档的单词,一般比较大
倒排索引(Posting List):记录单词倒排列表的关联信息
(3).倒排索引库内存结构
根据倒排索引查出索引id—>根据id 查询文档 (这里维护b+tree的内存结构,做到快速查询)
每个文档字段都有自己的倒排索引
(4).分词
分词是指将文本转换成一系列单词(term or token)的过程,也可以叫做文本分析,在es里面称为Analysis
分词机制
分词机制 | 说明 |
Character Filter | 对原始文本进行处理 例:去除html标签、特殊字符等 |
Tokenizer | 将原始文本进行分词 例:培训机构–>培训,机构 |
Token Filters | 将原始文本进行分词 例:转小写、删除语气词、近义词和同义词等 |
其中Character Filters 操作是在分词前进行文本处理,如增加、删除或替换字符等,包括如下所示:
分词机制说明:
分词测试
请求
POST _analyze
{
"analyzer": "standard",
"text":"hello 1111"
}
响应
{
"tokens": [
{
"token": "hello",
"start_offset": 0,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "1111",
"start_offset": 6,
"end_offset": 10,
"type": "<NUM>",
"position": 1
}
]
}
es 默认分词器为:standard分词器 就是标准分词器
12. 文档操作
(1).创建一个文档
格式如下,其中id 可以不设置,此时put 改为post
PUT/POST {index}/{type}/{id}
{
“”:””
}
请求:
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
响应:
{
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 1,
"created": true
}
(2).获取文档
想要从Elasticsearch中获取文档,我们使用同样的_index、_type、_id,但是HTTP方法改为GET:
GET /website/blog/123?pretty
响应包含了现在熟悉的元数据节点,增加了_source字段,它包含了在创建索引时我们发送给Elasticsearch的原始文档。
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 1,
"found" : true,
"_source" : {
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
}
检索文档的一部分
通常,GET请求将返回文档的全部,存储在_source参数中。但是可能你感兴趣的字段只是title。请求个别字段可以使用_source参数。多个字段可以使用逗号分隔:
GET /website/blog/123?_source=title,text
{
"_index": "website",
"_type": "blog",
"_id": "123",
"_version": 1,
"found": true,
"_source": {
"text": "Just trying this out...",
"title": "My first blog entry"
}
}
批量操作用POST website/blog/_mget
{
“ids”:[“2”,“1”]
}
(3).更新文档,与创建文档语法一样
请求:
POST /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
响应:
在响应中,我们可以看到Elasticsearch把_version增加了。
{
"_index" : "website",
"_type" : "blog",
"_id" : "123",
"_version" : 2,
"created": false <1>
}
(4).删除文档
删除文档的语法模式与之前基本一致,只不过要使用DELETE方法:
DELETE /website/blog/123
(5).局部更新文档
如下,tags 和views 字段内容被修改
POST /website/blog/1/_update
{
"doc" : {
"tags" : [ "testing" ],
"views": 0
}
}
检索文档文档显示被更新的_source字段:
{
"_index": "website",
"_type": "blog",
"_id": "1",
"_version": 3,
"found": true,
"_source": {
"title": "My first blog entry",
"text": "Starting to get the hang of this...",
"tags": [ "testing" ], <1>
"views": 0 <1>
}
}
(6).批量插入
每个json之间不能有换行\n,使用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
}
13. es 的mapping
mapping作用:定义表的结构,控制索引存储数据的设置
类似定义mysql 中表字段的名称字段类型name varchar …bigint int…
a.定义Index下的字段名(Field Name)
b.定义字段的类型,比如数值型、字符串型、布尔型等
c.定义倒排索引相关的配置,比如documentId、记录position、打分等
mapping不进行配置时,自动创建的mapping,es自动推倒
(1)获取mapping
GET /atguigu/_mapping
{
"atguigu": { #索引名称
"mappings": { #mapping设置
"student": { #type名称
"properties": { #字段属性
"clazz": {
"type": "text", #字段类型,字符串默认类型
"fields": { #子字段属性设置
"keyword": { #分词类型(不分词)
"type": "keyword",
"ignore_above": 256
}
}
},
"description": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
(2)自定义mapping
PUT my_index
{
"mappings":{
"doc":{
"dynamic":false,
"properties":{
"title":{
"type":"text"
},
"name":{
"type":"keyword"
},
"age":{
"type":"integer"
}
}
}
}
}
dynamic设置
a.true:允许自动新增字段(默认的配置)
b.False:不允许自动新增字段,但是文档可以正常写入,无法对字段进行查询操作
c.strict:文档不能写入(如果写入会报错) 不能新增字段
14.Search API(URI)
ing