Elasticsearch
入门
- 索引一个文档
通过一个简单的put请求,指定id索引一个文档:PUT /customer/_doc/1
{
"name":"John Doe"
}
customer为索引,_doc为类型,可以不写,该属性会在以后版本中废弃。如果该索引不存在会自动创建,请求成功的响应信息如下:
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"name" : "Jone Doe",
"age" : 12
}
}
_version
为版本号,第一次创建值为1,每次数据修改自增一,_seq_no
序列号,和版本号一样,数据更新自增1,_primary_term
分片改变自增1,found
查询是否成功,_source
查询到的数据。
- 批量索引文档
创建一个bank
文档,使用_bulk将数据索引到bank
文档中:/bank/_bulk
数据内容复制到此
开始搜索
- GET /bank/_search:搜索bank下的所有文档
GET /bank/_search
{
"query": {"match_all": {}}
}
返回的数据中es会自动给我们分页,默认是每页十条数据,返回数据:
{
"took" : 2,// Elasticsearch运行查询多长时间(以毫秒为单位)
"timed_out" : false,//搜索请求是否超时
"_shards" : {//搜索了多少个分片以及成功,失败或跳过了多少个分片。
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1000,//找到了多少个匹配的文档
"relation" : "eq"
},
"max_score" : null,//找到的最相关文件的分数
"hits" : [
{
"_index" : "bank",
"_type" : "_doc",
"_id" : "0",
"_score" : null,//文档的相关性得分(使用时不适用match_all)
"_source" : {
"account_number" : 0,
"balance" : 16623,
"firstname" : "Bradshaw",
"lastname" : "Mckenzie",
"age" : 29,
"gender" : "F",
"address" : "244 Columbus Place",
"employer" : "Euron",
"email" : "bradshawmckenzie@euron.com",
"city" : "Hobucken",
"state" : "CO"
},
"sort" : [//文档的排序位置(不按相关性得分排序时)
0
]
}
]
}
}
可以用form
和size
显示页码和每页显示的数据数量
GET /bank/_search
{
"query": {
"match": {
"address": "Place"
}
},
"from": 1,
"size": 5,
"sort": [
{
"account_number": {
"order": "asc"
}
}
]
}
使用match
查询:GET /bank/_search
{
"query": {
"match": {
"address": "mill lane"
}
}
}
该查询是查询address
字段中含有mill
或lane
的数据,匹配mill lane
可以用match_phrase
GET /bank/_search
{
"query": {
"match_phrase": {
"address": "mill lane"
}
}
}
构造更复杂的可以使用bool
来构建多条件查询。可根据must
(必须匹配),should
(期望匹配),filter
(过滤)和must_not
(必须不匹配)指定条件。bool
中的这些元素称为子查询,文档满足must
或should
的标准程度都会增加相关性得分,分数越高越符合搜索条件。must_not
中的条件被视为过滤器,它会影响文档是否出现,不影响相关性得分。也可以显示的使用过滤器filter
。例如下面内容:
/bank/_search
查询年龄在20-30之间的,期望城市是Hobucken,薪水在20000-30000之间的。期望的值不满足也没关系,满足了得分会更高
{
"query": {
"bool": {
"must": [
{"range": {
"age": {
"gte": 20,
"lte": 30
}
}}
],
"should": [
{"match": {
"city.keyword": "Hobucken"
}}
],
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}
聚合
对查询出来的数据,还可以进行分析和汇总,语法如下:
{
"aggs": {//聚合
"my-agg-name": {//聚合名字
"terms": {//聚合操作,terms:对字段进行聚合
"field": "my-field"//需要聚合的字段
}
}
}
}
例:查询每个年龄段的人数 GET /bank/_search
GET /bank/_search
{
"aggs": {
"age_term": {
"terms": {
"field": "age"
}
}
}
}
返回的聚合信息如下:
"aggregations" : {
"age_term" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 463,
"buckets" : [
{
"key" : 31,
"doc_count" : 61
},
{
"key" : 39,
"doc_count" : 60
},
{
"key" : 26,
"doc_count" : 59
},
{
"key" : 32,
"doc_count" : 52
},
{
"key" : 35,
"doc_count" : 52
},
{
"key" : 36,
"doc_count" : 52
},
{
"key" : 22,
"doc_count" : 51
},
{
"key" : 28,
"doc_count" : 51
},
{
"key" : 33,
"doc_count" : 50
},
{
"key" : 34,
"doc_count" : 49
}
]
}
}
聚合后的数据还可以再聚合,如查询每个年龄段平均收入 GET bank/_search
{
"aggs": {
"age_term": {
"terms": {
"field": "age"
},
"aggs": {
"age_balance_avg": {
"avg": {
"field": "balance"
}
}
}
}
}
}
返回的聚合信息:
"aggregations" : {
"age_term" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 463,
"buckets" : [
{
"key" : 31,
"doc_count" : 61,
"age_balance_avg" : {
"value" : 28312.918032786885
}
},
{
"key" : 39,
"doc_count" : 60,
"age_balance_avg" : {
"value" : 25269.583333333332
}
},
{
"key" : 26,
"doc_count" : 59,
"age_balance_avg" : {
"value" : 23194.813559322032
}
},
{
"key" : 32,
"doc_count" : 52,
"age_balance_avg" : {
"value" : 23951.346153846152
}
},
{
"key" : 35,
"doc_count" : 52,
"age_balance_avg" : {
"value" : 22136.69230769231
}
},
{
"key" : 36,
"doc_count" : 52,
"age_balance_avg" : {
"value" : 22174.71153846154
}
},
{
"key" : 22,
"doc_count" : 51,
"age_balance_avg" : {
"value" : 24731.07843137255
}
},
{
"key" : 28,
"doc_count" : 51,
"age_balance_avg" : {
"value" : 28273.882352941175
}
},
{
"key" : 33,
"doc_count" : 50,
"age_balance_avg" : {
"value" : 25093.94
}
},
{
"key" : 34,
"doc_count" : 49,
"age_balance_avg" : {
"value" : 26809.95918367347
}
}
]
}
}
常用的REST API
索引相关api
- 创建一个索引:PUT /index,索引名称必须遵循一下规定
- 只能小写
- 不能包含
\
,/
,*
,?
,"
,<
,>
,|
,空格
,,
,#
- 在版本7.0之前可以包含
:
,但之后废除了 - 不能以
-
,_
,+
开头 - 不能是
.
或..
- 长度不能大于255
- 以
.
开头的名称已经被废弃了,除了隐藏索引和由插件管理的内部索引
- 删除一个索引:DELETE /index
- 更多与索引相关的api可查看elasticsearch官方文档
文档相关api
- 插入一个文档
- PUT /index/_doc/id
- POST /index/_doc
- PUT /index/_create/id
- POST /index/_create/id
index
为索引名,_doc
和_create
为固定写法,id
为文档id,只用第二种POST /index/_doc
才可不传id,使用系统分配的id
- 指定id删除文档:
DELETE /index/_doc/id
- 指定id更新文档
POST /index/id
,该请求不管提交的内容是否和原内容一样,版本号都会自增1POST /index/_update/id
,改请求会对比原有内容,如果数据为发生改变版本号不会自增
批量操作api
_bluk
在单个请求中可以处理多个索引或删除操作,用法:POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
index
有则更新,无则插入,更新时不会检查原数据,版本号一直会自增1delete
删除文档create
创建文档update
更新文档,会检查原数据,如果数据没发生改变,版本号不会自增_index
索引名_id
文档id
新增,更新两行为一个操作,删除一行为一个操作
mapping映射
在创建索引时,可以预先定义索引的字段,用法:PUT /test
{
"mappings": {
"properties": {
"name":{//字段名
"type": "text"//类型
},
"age":{
"type": "integer"
},
"email":{
"type": "keyword"
}
}
}
}
es字段类型可查看mapping-types。
nested类型
字段类型为keyword
的只能用于精确匹配。es没有数组类型,任何字段类型的都能写成数组,但是类型要一样。如果数组元素是对象,需要声明为nested
类型,否则会扁平化。官方示例:PUT my-index-000001/_doc/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
上面数据将会转化为如下结构:
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
当查询user.first
为Alice
,user.last
为Smith
将会出现两个结果:
GET my_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"user.first": "Alice"
}
},
{
"match": {
"user.last": "Smith"
}
}
]
}
}
}
返回数据:
[
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.5753642,
"_source" : {
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
}
]
在添加的文档中是没有Alice Simth
的user.first
与user.last
的关联已经消失了。
要解决此问题需要在声明字段映射时将字段类型声明为nested
类型:PUT my_index
{
"mappings": {
"properties": {
"user":{
"type": "nested"
}
}
}
}
在查询时也要指定nested
查询:GET my_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{
"term": {
"user.first": {
"value": "John"
}
}
},
{
"term": {
"user.last": {
"value": "White"
}
}
}
]
}
}
}
}
}
在这次查询中,查询John White
返回的数据便是空了。