ElasticSearch入门之基本概念和RESTful api

ElasticSearch入门之基本概念和RESTful api

    • 1、简介
    • 2、基本概念
      • 2.1索引
      • 2.2文档
      • 2.3文档类型(ES7中已移除)
      • 2.4字段
      • 2.5映射
      • 2.6接近实时 NRT
      • 2.7 集群 cluster
      • 2.8 节点 node
      • 2.9 分片和复制 shards&replicas
    • 3、RESTful api
      • 3.1准备工作
      • 3.2创建索引
      • 3.3插入数据
      • 3.4更新数据
      • 3.5删除数据
      • 3.6搜索数据
      • 3.7DSL搜索
      • 3.8高亮显示
      • 3.9聚合

1、简介

ElasticSearch是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎,它是基于RESTful web接口的,采用java开发,并作为Apache许可条款下的开源发布,是当前流行的企业级搜索引擎。

2、基本概念

Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。Elasticsearch比传统关系型数据库如下:

Relational DB ‐> Databases ‐> Tables ‐> Rows ‐> Columns
Elasticsearch ‐> Indices‐> Types‐> Documents ‐> Fields

2.1索引

  • 索引(index)是ElasticSearch对逻辑数据的逻辑存储,一个索引就是一个拥有几分相似特征的文档的集合,所以它可以分为更小的部分。
  • 可以把索引当做关系数据库中的表,索引的结构是为快速有效的全文索引准备的,它不存储原始值。
  • 一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。
  • ES可以把索引存放在一台机器或多台机器上,在一个集群中,可以定义任意多的索引,每个索引有一个或多个分片(shard),每个分片可以有多个副本(replica)。

2.2文档

  • 文档(document)是存储在ES中的主要实体,一个文档是一个可被索引的基础信息单元,相当于数据库表中的一行记录。
  • ES和MongoDB中的文档类似,都可以有不同的结构,但ES的文档中,相同字段必须有相同的类型。
  • 在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。
  • 文档由多个字段组成,每个字段可以多次出现在一个文档里,这样的字段叫做多值字段。

2.3文档类型(ES7中已移除)

  • 类型(type)相当于数据库中的表。(虽然可以这样假设,但是并不完全正确,在关系型数据库里,"表"是相互独立的,一个“表”里的列和另外一个“表”的同名列没有关系,互不影响。但在类型里字段不是这样的。在一个Elasticsearch索引里,所有不同类型的同名字段内部使用的是同一个lucene字段存储。在同一个索引中,存储仅有小部分字段相同或者全部字段都不相同的文档,会导致数据稀疏,影响Lucene有效压缩数据的能力。)
  • 在一个索引中,可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。
  • 不同的文档类型不能为相同的属性设置不同的类型。例如,在同一索引中的所有文档类型中,一个叫title的字段必须具有相同的类型。

2.4字段

  • 字段(field)相当于是数据表的字段,对文档数据根据不同属性进行的分类标识。

2.5映射

  • 映射(mapping)是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等。
  • 处理es里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。

2.6接近实时 NRT

  • Elasticsearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延迟(通常是1秒以内)

2.7 集群 cluster

  • 一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。
  • 一个集群由一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。

2.8 节点 node

  • 一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。
  • 和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对应于ES集群中的哪些节点。
  • 个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。
  • 在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。

2.9 分片和复制 shards&replicas

  • 一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。
  • 每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主要有两方面的原因:
    • 1)允许你水平分割/扩展你的内容容量。
    • 2)允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量。
  • 至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的。
  • 在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。
  • 复制之所以重要,有两个主要原因: 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行。总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。
  • 分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变分片的数量。
  • 默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。

3、RESTful api

在ElasticSearch中,提供了功能丰富的restful api操作,包括CURD操作和创建索引,删除索引等。

3.1准备工作

首先需要打开ElasticSearch服务,访问127.0.0.1:9200出现下面界面表示打开成功:
ElasticSearch入门之基本概念和RESTful api_第1张图片

然后安装elasticsearch-head插件,安装成功后如下:
ElasticSearch入门之基本概念和RESTful api_第2张图片
最后安装postman应用或者安装Advanced REST Client谷歌浏览器插件,都是用来发送http请求的。linux安装postmanl链接

3.2创建索引

创建一个简单的空索引,索引的名字为blog,如下:
ElasticSearch入门之基本概念和RESTful api_第3张图片
采用put的方式,url为服务地址加上索引的名称,请求参数如下:

{
	"settings":{
		"index":{
			"number_of_shards":"2",
			"number_of_replicas":"0"
		}
	}
}

number_of_shards为片数,number_of_replicas为副本数。点击发送之后,状态码为200表示创建成功,刷新可以看到多了一个blog索引:
ElasticSearch入门之基本概念和RESTful api_第4张图片

3.3插入数据

向索引blog1中插入一条user类型的数据时,_id设置为1001,请求地址为http://127.0.0.1:9200/blog1/user/1001,采用post方式。也可以不设置_id,就会使用自动生成的_id,这是一条数据的唯一标识符。

{
	"id":1001,
	"name":"张三",
	"age":20,
	"sex":"男"
}

会出现错误如下,说名这个索引是只读状态。

{
    "error": {
        "root_cause": [
            {
                "type": "cluster_block_exception",
                "reason": "index [blog1] blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];"
            }
        ],
        "type": "cluster_block_exception",
        "reason": "index [blog1] blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];"
    },
    "status": 403
}

解决方法,终端运行下面命令:

curl -XPUT -H "Content-Type: application/json" http://127.0.0.1:9200/blog1/_settings -d '{"index.blocks.read_only_allow_delete": null}'

或者在postman中执行PUT http://127.0.0.1:9200/blog1/_settings

{
"index.blocks.read_only_allow_delete": null
}

其中,blog1换成你的索引名称,也可以换成_all表示所有索引。
再次发送请求,响应结果如下,表示插入数据成功:

{
    "_index": "blog1",
    "_type": "user",
    "_id": "1001",
    "_version": 3,
    "result": "updated",
    "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 2,
    "_primary_term": 2
}

注:这是非结构化的索引,不需要事先创建,直接插入数据默认创建索引。

3.4更新数据

在elasticsearch中,文档数据是不可以修改的,但是可以通过覆盖的方式进行更新。

PUT http://127.0.0.1:9200/blog1/user/1001
{
	"id":1001,
	"name":"张三",
	"age":23,
	"sex":"女"
}

查看数据,如图以及修改了:
在这里插入图片描述
数据虽然被更新了,但是确实全部数据的覆盖,那么能不能局部更新呢,其实是可以的,在内部,依然会查询到这个文档数据,然后进行覆盖,步骤如下:
1.从旧文档中检索json
2.进行修改
3.删除旧文档
4.索引新文档
如下,把年龄更改为26,请求地址为http://127.0.0.1:9200/blog1/user/1001/_update

POST http://127.0.0.1:9200/blog1/user/1001/_update
{
	"doc":{
		"age":26
	}
}

查看结果:
在这里插入图片描述

3.5删除数据

删除数据只需要在postman中执行DELETE http://127.0.0.1:9200/blog1/user/1001即可,相应的数据如下,表示删除成功。

{
    "_index": "blog1",
    "_type": "user",
    "_id": "1001",
    "_version": 7,
    "result": "deleted",
    "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 6,
    "_primary_term": 2
}

注:删除一个文档不会立即从磁盘上移除,只是被标记为已删除状态,Elasticsearch会在你之后添加更多索引的时候在后台进行删除内容的清理。

3.6搜索数据

1.搜索一条数据:只需要执行GET http://127.0.0.1:9200/blog1/user/1001即可,其中1001是_id
返回结果如下:

{
	"_index": "blog1",
	"_type": "user",
	"_id": "1001",
	"_version": 1,
	"_seq_no": 7,
	"_primary_term": 2,
	"found": true,
	"_source": {
		"id": 1001,
		"name": "张三",
		"age": 23,
		"sex": "女"
	}
}

2.搜索全部数据:GET http://127.0.0.1:9200/blog1/user/_search,默认返回10条数据。
3.关键字搜索:例如根据年龄搜索,GET http://127.0.0.1:9200/blog1/user/_search?q=age:23
返回的数据:

{
	"took": 2,
	"timed_out": false,
	"_shards": {
		"total": 2,
		"successful": 2,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
		"total": {
			"value": 1,
			"relation": "eq"
		},
		"max_score": 1.0,
		"hits": [
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "1001",
				"_score": 1.0,
				"_source": {
					"id": 1001,
					"name": "张三",
					"age": 23,
					"sex": "女"
				}
			}
		]
	}
}

3.7DSL搜索

Elasticsearch提供了丰富且灵活的查询语叫做DSL查询,它允许构建更加复杂,强大的查询。post http://127.0.0.1:9200/blog1/user/_search

{
	"query":{
		"match":{
			"age":23
		}
	}
}

响应数据:

{
	"took": 2,
	"timed_out": false,
	"_shards": {
		"total": 2,
		"successful": 2,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
		"total": {
			"value": 1,
			"relation": "eq"
		},
		"max_score": 1.0,
		"hits": [
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "1001",
				"_score": 1.0,
				"_source": {
					"id": 1001,
					"name": "张三",
					"age": 23,
					"sex": "女"
				}
			}
		]
	}
}

查询年龄大于20岁,姓名为男的数据,请求体如下:

{
	"query":{
		"bool":{
			"filter":{
				"range":{
					"age":{
						"gt":20
					}
				}
			},
			"must":{
				"match":{
					"sex":"男"
				}
			}
		}
	
	}
}

返回结果:

{
	"took": 24,
	"timed_out": false,
	"_shards": {
		"total": 2,
		"successful": 2,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
		"total": {
			"value": 2,
			"relation": "eq"
		},
		"max_score": 0.2876821,
		"hits": [
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "1001",
				"_score": 0.2876821,
				"_source": {
					"id": 1002,
					"name": "李四",
					"age": 25,
					"sex": "男"
				}
			},
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "jmsZD20Bk9NfkJ2KxpRa",
				"_score": 0.18232156,
				"_source": {
					"id": 1004,
					"name": "张三",
					"age": 21,
					"sex": "男"
				}
			}
		]
	}
}

全文搜索,请求体如下:

{
	"query":{
		"match":{
			"name":"张三 李四"
		}
	}
}

搜索结果为:

{
	"took": 13,
	"timed_out": false,
	"_shards": {
		"total": 2,
		"successful": 2,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
		"total": {
			"value": 2,
			"relation": "eq"
		},
		"max_score": 1.3862944,
		"hits": [
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "jmsZD20Bk9NfkJ2KxpRa",
				"_score": 1.3862944,
				"_source": {
					"id": 1004,
					"name": "张三",
					"age": 21,
					"sex": "男"
				}
			},
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "1001",
				"_score": 0.5753642,
				"_source": {
					"id": 1002,
					"name": "李四",
					"age": 25,
					"sex": "男"
				}
			}
		]
	}
}

3.8高亮显示

请求体

{
	"query":{
		"match":{
			"name":"张三 李四"
		}
	},
	"highlight":{
		"fields":{
			"name":{}
			
		}
	}
}

返回结果:

{
	"took": 72,
	"timed_out": false,
	"_shards": {
		"total": 2,
		"successful": 2,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
		"total": {
			"value": 2,
			"relation": "eq"
		},
		"max_score": 1.3862944,
		"hits": [
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "jmsZD20Bk9NfkJ2KxpRa",
				"_score": 1.3862944,
				"_source": {
					"id": 1004,
					"name": "张三",
					"age": 21,
					"sex": "男"
				},
				"highlight": {
					"name": [
						""
					]
				}
			},
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "1001",
				"_score": 0.5753642,
				"_source": {
					"id": 1002,
					"name": "李四",
					"age": 25,
					"sex": "男"
				},
				"highlight": {
					"name": [
						""
					]
				}
			}
		]
	}
}

这里涉及到中文分词的问题,将在以后谈到

3.9聚合

请求体:

{
	"aggs":{
		"all_interests":{
			"terms":{
				"field":"age"
			}
		}
	}
}

响应结果:

{
	"took": 50,
	"timed_out": false,
	"_shards": {
		"total": 2,
		"successful": 2,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
		"total": {
			"value": 4,
			"relation": "eq"
		},
		"max_score": 1.0,
		"hits": [
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "jGsYD20Bk9NfkJ2K1JRX",
				"_score": 1.0,
				"_source": {
					"id": 1003,
					"name": "王五",
					"age": 18,
					"sex": "男"
				}
			},
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "jmsZD20Bk9NfkJ2KxpRa",
				"_score": 1.0,
				"_source": {
					"id": 1004,
					"name": "张三",
					"age": 21,
					"sex": "男"
				}
			},
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "kGsnD20Bk9NfkJ2KRZTb",
				"_score": 1.0,
				"_source": {
					"id": 1005,
					"name": "赵六",
					"age": 21,
					"sex": "男"
				}
			},
			{
				"_index": "blog1",
				"_type": "user",
				"_id": "1001",
				"_score": 1.0,
				"_source": {
					"id": 1002,
					"name": "李四",
					"age": 25,
					"sex": "男"
				}
			}
		]
	},
	"aggregations": {
		"all_interests": {
			"doc_count_error_upper_bound": 0,
			"sum_other_doc_count": 0,
			"buckets": [
				{
					"key": 21,
					"doc_count": 2
				},
				{
					"key": 18,
					"doc_count": 1
				},
				{
					"key": 25,
					"doc_count": 1
				}
			]
		}
	}
}

上半部分是查询的数据,下半部分是根据年龄进行的聚合统计。



你可能感兴趣的:(Elasticsearch,Elasticsearch)