插入数据
一旦你启动并运行集群,你就可以创建数据了。Elasticsearch 有多种方式插入数据,但最终它们都执行同样的操作,将 JSON 文档放入 Elasticsearch 索引中。
你可以使用简单的 PUT 请求去执行操作,请求须指定文档的索引名称,唯一的文档 ID,以及请求体中一个或多个键值对。
PUT /customer/_doc/1 { "name": "John Doe" }
这个请求(如不存在)将自动创建一个 ID 为 1 的新文档,并储存键值对,并为其建立索引。
由于这是一个新文档,返回的结果显示新创建的文档版本号为 1:
{ "_index" : "customer", "_type" : "_doc", "_id" : "1", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 26, "_primary_term" : 4 }
你可以在集群里任意节点去获取文档,你也可以 GET 请求指定 ID 文档
GET /customer/_doc/1
返回结果显示找到里对应的指定文档,并返回了原始字段信息
{ "_index" : "customer", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 26, "_primary_term" : 4, "found" : true, "_source" : { "name": "John Doe" } }
批量插入数据
如果有大量的文档需要插入,你可以使用 BULK API 批量插入数据。使用 Bulk API 要比单独请求提交要快,是因为它最大限度地减少了网络传输次数。
最佳批量插入大小取决于许多因素:文档大小和复杂性、索引、搜索负载以及集群的可用资源。每次批量处理最好在 1000 ~ 5000 个文档,文档大小最好是在 5M ~ 15M 之间。
将数据批量导入 Elasticsearch,你就可以开始搜索和分析了。
下载 acounts.jsondemo数据。随机生成的 demo 数据展示了以下的用户信息:
{ "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" }
使用_bulk
请求将账户数据导入到银行文档中:
curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@C:/user/accounts.json
注意:
@C:/user/accounts.json,是该文件再你电脑中的存储位置
返回结果显示了成功导入了 1000 个文档
" curl "localhost:9200/_cat/indices?v"
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open bank l7sSYV2cQXmu6_4rJWVIww 5 1 1000 0 128.6kb 128.6kb
搜索
一旦你开始在 Elasticsearch 插入数据,你就可以通过_search 方式发送请求来进行搜索,如果使用匹配搜索功能,在请求体中使用 Elasticsearch Query DSL 指定搜索条件。你也可以在请求头指定要搜索的索引名称。
如下图所示:搜索银行索引中,所有账号按照 account_number 排序:
GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ] }
默认情况下,会返回符合条件搜索的前 10 个文档:
{ "took" : 63, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value": 1000, "relation": "eq" }, "max_score" : null, "hits" : [ { "_index" : "bank", "_type" : "_doc", "_id" : "0", "sort": [0], "_score" : null, "_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"} }, { "_index" : "bank", "_type" : "_doc", "_id" : "1", "sort": [1], "_score" : null, "_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"} }, ... ] } }
响应体里还提供了有关搜索请求的相关信息:
took – 查询花费时长(毫秒)
timed_out – 请求是否超时
_shards – 搜索了多少分片,成功、失败或者跳过了多个分片(明细)
max_score – 最相关的文档分数
hits.total.value - 找到的文档总数
hits.sort - 文档排序方式 (如没有则按相关性分数排序)
hits._score - 文档的相关性算分 (match_all 没有算分)
每个搜索请求都是独立的:Elasticsearch 不维护任何请求中的状态信息。如果做分页的话,请在请求中指定 From 和 Size 参数。
如图所示:搜索第 10 到 19 的数据
GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ], "from": 10, "size": 10 }
现在你已经了解如何提交最基本的搜索请求了,则可以开始构建比 match_all 更有趣的查询了。
想搜索特定的字段,可以使用匹配查询。如下所示,请求搜索地址字段以查询地址中包含 mill 或 lane 的客户
GET /bank/_search { "query": { "match": { "address": "mill lane" } } }
如果要全部匹配而不是仅仅是包含关键字之一,你需要使用 match_phrase 而不是 match。(译者注:match 和 match_phrase 的区别就像是 or 和 and 的区别) 如图所示:
在请求中查询地址中同时包含 mill 和 lane 的客户:
GET /bank/_search { "query": { "match_phrase": { "address": "mill lane" } } }
如果要构造更复杂的查询,可以使用布尔查询来组合多个查询条件,must match、should match、must not match
如图所示:请求在银行索引里搜索年龄是 40 的,但不居住在爱达荷州 (ID) 的客户:
GET /bank/_search { "query": { "bool": { "must": [ { "match": { "age": "40" } } ], "must_not": [ { "match": { "state": "ID" } } ] } } }
布尔查询中每个 must,should,must_not 都被称为查询子句。每个
must 或者 should 查询子句中的条件都会影响文档的相关得分。得分越高,文档跟搜索条件匹配得越好。默认情况下,Elasticsearch 返回的文档会根据相关性算分倒序排列。
must_not 子句中认为是过滤条件。它会过滤返回结果,但不会影响文档的相关性算分,你还可以明确指定任意过滤条件去筛选结构化数据文档。
如图所示:请求搜索余额在 20000 ~ 30000(包括 30000) 之间的账户
GET /bank/_search { "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000 } } } } } }
使用聚合分析
Elasticsearch 聚合让你看到一些有关搜索结果元信息,返回结果能显示例如:“德克萨斯州有多少个开户的人?” 或者 “田纳西州的平均帐户余额是多少?”。你可以搜索文档,过滤 hits,使用聚合去分析并返回结果。
如图所示:请求使用 terms 聚合对 bank 索引中对所有还在账户进行分组,并安装返回前 10 个账户数最多的州:
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" } } } } { "took": 29, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped" : 0, "failed": 0 }, "hits" : { "total" : { "value": 1000, "relation": "eq" }, "max_score" : null, "hits" : [ ] }, "aggregations" : { "group_by_state" : { "doc_count_error_upper_bound": 20, "sum_other_doc_count": 770, "buckets" : [ { "key" : "ID", "doc_count" : 27 }, { "key" : "TX", "doc_count" : 27 }, { "key" : "AL", "doc_count" : 25 }, { "key" : "MD", "doc_count" : 25 }, { "key" : "TN", "doc_count" : 23 }, { "key" : "MA", "doc_count" : 21 }, { "key" : "NC", "doc_count" : 21 }, { "key" : "ND", "doc_count" : 21 }, { "key" : "ME", "doc_count" : 20 }, { "key" : "MO", "doc_count" : 20 } ] } } }{ "took": 29, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped" : 0, "failed": 0 }, "hits" : { "total" : { "value": 1000, "relation": "eq" }, "max_score" : null, "hits" : [ ] }, "aggregations" : { "group_by_state" : { "doc_count_error_upper_bound": 20, "sum_other_doc_count": 770, "buckets" : [ { "key" : "ID", "doc_count" : 27 }, { "key" : "TX", "doc_count" : 27 }, { "key" : "AL", "doc_count" : 25 }, { "key" : "MD", "doc_count" : 25 }, { "key" : "TN", "doc_count" : 23 }, { "key" : "MA", "doc_count" : 21 }, { "key" : "NC", "doc_count" : 21 }, { "key" : "ND", "doc_count" : 21 }, { "key" : "ME", "doc_count" : 20 }, { "key" : "MO", "doc_count" : 20 } ] } } }
如图所示:在返回结果中 buckets 的值是字段 state 的桶。 doc_count 表示每州的账户数。你可以看到爱达荷州中有 27 个帐户,由于 "size": 0 表示了返回只有聚合结果,无具体数据。
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } }
你可以使用组合聚合来构建更为复杂的统计数据。如图所示:请求将 avg
聚合嵌套在 group_by_state
聚合内,以计算每州的平均账户余额
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword" }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } }
如图所示:你也可以不按内置结果进行排序,而可以使用聚合后的 average_balance
字段进行排序
GET /bank/_search { "size": 0, "aggs": { "group_by_state": { "terms": { "field": "state.keyword", "order": { "average_balance": "desc" } }, "aggs": { "average_balance": { "avg": { "field": "balance" } } } } } }
除了这些基本的桶跟指标聚合之外,Elasticsearch 还提供了其他类型的聚合,用于对多个字段进行操作和分析特定类型的数据,如日期、IP 和地理数据。你还可以将单个聚合的结果送到管道聚合中进行深一步分析。