> 文章列表 > Elasticsearch简单搜索以及聚合分析

Elasticsearch简单搜索以及聚合分析

Elasticsearch简单搜索以及聚合分析

1.批量索引文档

如果你有大量文档要索引,你能通过批量 APIbulk API) 来批量提交它们。批量文档操作比单独提交请求显著更快,因为它极简了网络往返。

最佳的批量数量取决于许多因素:文档的大小和复杂度、索引和搜索的负载以及集群可用资源。一种好的方式是批量处理 1,000 到 5,000 个文档,且总负载在 5 MB 到 15 MB。基于这个,你能尝试找到最佳的方式。

向 Elasticsearch 导入一些数据,你就能开始搜索和分析:

1.1 下载 accounts.json (opens new window)示例数据集。这个随机生成的数据集文档表示具体以下信息的用户账户

1.2  使用以下的 _bulk 请求将账户数据索引到银行(bank) 索引中:

curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@accounts.json"
curl "localhost:9200/_cat/indices?v=true"

2. 开始搜索

例如,以下请求获取按账号排序的银行(bank)索引中的所有文档:

GET /bank/_search
{"query": { "match_all": {} },"sort": [{ "account_number": "asc" }]
}

默认情况下,响应的命中部分(hits section)包含符合搜索条件的前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 —— Elasticsearch 执行查询的耗时(毫秒)
  • 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 更有趣的查询。

为了在字段中搜索指定词语,你可以使用匹配查询。例如,以下的查询搜索地址(address)字段,用以查找地址包含 mill 或 lane的客户:

GET /bank/_search
{"query": { "match": { "address": "mill lane" } }
}

为了执行短语搜索而不是匹配单独的词语,你可以使用 match_phrase 替代 match。例如,以下请求只匹配包含短语 mill lane 的地址:

GET /bank/_search
{"query": { "match_phrase": { "address": "mill lane" } }
}

为了构造更复杂的查询,你可以使用包含多个查询条件的 bool 的查询。你可以按必须的(必须匹配)、可选的(应该匹配)或者不必的(必须不匹配)来指定条件。

例如,以下请求搜索银行(bank)索引中属于 40 岁客户的账号,但排除其中住在爱达荷州(ID)的人:

GET /bank/_search
{"query": {"bool": {"must": [{ "match": { "age": "40" } }],"must_not": [{ "match": { "state": "ID" } }]}}
}

布尔查询中的每个 mustshould 和 must_not 都称为查询子句。文档满足每个 must 或 should 条件子句的程度,有助于文档相关性的分数。分数越高,文档越符合你的搜索条件。默认情况下,Elasticsearch 返回按相关性分数排序的文档。

must_not 子句中的条件被认作过滤器。它影响文档是否包含在结果中,但不影响文档分数。你可以显式地指定任意的过滤器,用来包含或排除基于结构化数据的文档。

例如,以下请求使用范围过滤器用以限定结果中账户余额在 $20,000 和 $30,000(含)之间。3

GET /bank/_search
{"query": {"bool": {"must": { "match_all": {} },"filter": {"range": {"balance": {"gte": 20000,"lte": 30000}}}}}
}

3. 使用聚合分析结果 

例如,以下的请求使用一个词语聚合分组在银行(bank)索引中按州对所有账户分组,并按降序返回账户最多的十个州:

GET /bank/_search
{"size": 0,"aggs": {"group_by_state": {"terms": {"field": "state.keyword"}}}
}

响应中的桶(bucket)是州(state)字段的值。doc_count 显示每个州的账户数量。例如,你可以看到 ID(爱达荷州)有 27 个账户。由于这个请求设置 size=0,这个请求只包含聚合结果。

{"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} ]}}
}

你可以合并聚合来构建更复杂的数据摘要。例如,以下请求在前一个按州分组(group_by_state)聚合嵌套一个 avg 聚合,以计算每个州的平均账户余额。

GET /bank/_search
{"size": 0,"aggs": {"group_by_state": {"terms": {"field": "state.keyword"},"aggs": {"average_balance": {"avg": {"field": "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 地址以及地理数据。你还可以将单个聚合的结果输入管道聚合用于进一步的分析。