基本概念
索引
- 索引(index)是Elasticsearch对逻辑数据的逻辑存储,所以它可以分为更小的部分。
- 可以把索引看成关系型数据库的表,索引的结构是为快速有效的全文索引准备的,特别是它不存储原始值。
- 可以把Elasticsearch的索引看成MongoDB里的一个集合。
- Elasticsearch可以把索引存放在一台机器或者分散在多台服务器上,每个索引有一或多个分片(shard),每个分片可以有多个副本(replica)。
文档
- 存储在Elasticsearch中的主要实体叫文档(document)。用关系型数据库来类比的话,一个文档相当于数据库表中的一行记录。
- Elasticsearch和MongoDB中的文档类似,都可以有不同的结构,但Elasticsearch的文档中,相同字段必须有相同类型。
- 文档由多个字段组成,每个字段可能多次出现在一个文档里,这样的字段叫多值字段(multivalued)。
- 每个字段的类型,可以是文本、数值、日期等。字段类型也可以是复杂类型,一个字段包含其他子文档或者数组。
映射
- 所有文档写进索引之前都会先进行分析,如何将输入的文本分割为词条、哪些词条又会被过滤,这种行为叫做映射(mapping)。一般由用户自己定义规则
文档类型
- 在Elasticsearch中,一个索引对象可以存储很多不同用途的对象。例如,一个博客应用程序可以保存文章和评论。
- 每个文档可以有不同的结构。
- 不同的文档类型不能为相同的属性设置不同的类型。例如,在同一索引中的所有文档类型中,一个叫title的字段必须具有相同的类型。
RESTful API
在Elasticsearch中,提供了功能丰富的RESTful API的操作,包括基本的CRUD、创建索引、删除索引等操作。
1. 创建非结构化索引
在Lucene中,创建索引是需要定义字段名称以及字段的类型的,在Elasticsearch中提供了非结构化的索引,就是
不需要创建索引结构,即可写入数据到索引中,实际上在Elasticsearch底层会进行结构化操作,此操作对用户是透
明的。
创建空索引:
PUT http://172.16.55.185:9200/pippen
{
"settings": {
"index": {
"number_of_shards": "2", #分片数
"number_of_replicas": "0" #副本数
}
}
}
#删除索引
DELETE http://172.16.55.185:9200/pippen
{
"acknowledged": true
}
2. 插入数据
URL 规则
POST http://172.16.55.185:9200/{索引}/{类型}/
不指定ID时 es 将会随机产生一个ID
POST http://172.16.55.185:9200/pippen/user/1001
# 请求
{
"id": 1001,
"name": "张三",
"age": 20,
"sex": "男"
}
# 响应
{
"_index": "pippen",
"_type": "_doc",
"_id": "e2zkN3ABU2jSZT_ME8Ts",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
说明:非结构化的索引,不需要事先创建,直接插入数据默认创建索引。
3. 更新数据
在Elasticsearch中,文档数据是不为修改的,但是可以通过覆盖的方式进行更新
PUT http://172.16.55.185:9200/pippen/user/1001
{
"id":1001,
"name":"张三",
"age":21,
"sex":"女"
}
# 局部更新
# 注意:这里多了_update标识
POST http://172.16.55.185:9200/pippen/user/1001/_update
{
"doc":{
"age":23
}
}
4. 删除数据
在Elasticsearch中,删除文档数据,只需要发起DELETE请求即可
DELETE http://172.16.55.185:9200/pippen/user/1001
注意
result表示已经删除,version也更加了。
如果删除一条不存在的数据,会响应404
说明:
删除一个文档也不会立即从磁盘上移除,它只是被标记成已删除。
Elasticsearch将会在你之后添加更多索引的时候才会在后台进行删除内容的清理
5. 搜索数据
5.1 根据ID进行搜索
GET http://172.16.55.185:9200/pippen/user/e2zkN3ABU2jSZT_ME8Ts
#返回结果
{
"_index": "pippen",
"_type": "_doc",
"_id": "e2zkN3ABU2jSZT_ME8Ts",
"_version": 1,
"found": true,
"_source": { ## 原始数据
"id": 1001,
"name": "张三",
"age": 20,
"sex": "男"
}
}
5.2 搜索全部数据
响应:(默认返回10条数据)
GET http://172.16.55.185:9200/pippen/user/_search
{
"took": 41,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.0,
"hits": [
{
"_index": "pippen",
"_type": "_doc",
"_id": "e2zkN3ABU2jSZT_ME8Ts",
"_score": 1.0,
"_source": {
"id": 1001,
"name": "张三",
"age": 20,
"sex": "男"
}
}
]
}
}
6. 高亮显示
POST http://172.16.55.185:9200/pippen/user/_search
{
"query": {
"match": {
"name": "张三 李四"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}
7. 结构化查询
7.1 term查询
term
主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型):
http://172.16.55.185:9200/pippen/_doc/_search
# 请求
{
"query" : {
"term" : {
"age" : 20
}
}
}
# 响应
{
"took": 20,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.0,
"hits": [
{
"_index": "pippen",
"_type": "_doc",
"_id": "e2zkN3ABU2jSZT_ME8Ts",
"_score": 1.0,
"_source": {
"id": 1001,
"name": "张三",
"age": 20,
"sex": "男"
}
}
]
}
}
7.2 terms查询
terms
跟 term
有点类似,但 terms
允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配:
http://172.16.55.185:9200/pippen/_doc/_search
# 请求
{
"query" : {
"terms" : {
"age" : [20,21]
}
}
}
7.3 range查询
range
过滤允许我们按照指定范围查找一批数据
范围操作符包含:
gt :: 大于
gte :: 大于等于
lt :: 小于
lte :: 小于等于
http://172.16.55.185:9200/pippen/_doc/_search
# 请求
{
"query" : {
"range" : {
"age" : {
"gte": 20,
"lte": 22
}
}
}
}
7.4 exists 查询
exists
查询可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的 IS_NULL
条件
http://172.16.55.185:9200/pippen/_doc/_search
# 请求
{
"query" : {
"exists" : { # 必须包含
"field" :"age"
}
}
}
7.5 match查询
match
查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。如果你使用 match
查询一个全文本字段,它会在真正查询之前用分析器先分析 match
一下查询字符
{
"match": {
"tweet": "About Search"
}
}
如果用 match
下指定了一个确切值,在遇到数字,日期,布尔值或者 not_analyzed
的字符串时,它将为你搜索你给定的值:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}
7.6 bool查询
bool 查询可以用来合并多个条件查询结果的布尔逻辑,它包含一下操作符:
must
:: 多个查询条件的完全匹配,相当于 and
。
must_not
:: 多个查询条件的相反匹配,相当于 not
。
should
:: 至少有一个查询条件匹配, 相当于 or
。
这些参数可以分别继承一个查询条件或者一个查询条件的数组:
{
"bool": {
"must": { "term": { "folder": "inbox" }},
"must_not": { "term": { "tag": "spam" }},
"should": [
{ "term": { "starred": true }},
{ "term": { "unread": true }}
]
}
}
8. 过滤查询
POST http://172.16.55.185:9200/pippen/_doc/_search
{
"query": {
"bool": {
"filter": {
"term": {
"age": 20
}
}
}
}
}
查询和过滤的对比
-
一条过滤语句会询问每个文档的字段值是否包含着特定值。
-
查询语句会询问每个文档的字段值与特定值的匹配程度如何。
- 一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分 _score,并且 按照相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。
-
一个简单的文档列表,快速匹配运算并存入内存是十分方便的, 每个文档仅需要1个字节。这些缓存的过滤结果集与后续请求的结合使用是非常高效的。
-
查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比 过滤语句更耗时,并且查询结果也不可缓存
建议:
做精确匹配搜索时,最好用过滤语句,因为过滤语句可以缓存数据。