【全面详解】ElasticSearch 常见的14种查询大全代码示例
ElasticSearch 常见的查询大全,以及代码示例
Elasticsearch 简介
Elasticsearch 是一个高度可扩展的开源全文搜索和分析引擎,允许你以近实时的方式存储、搜索和分析大量数据。它通常用于复杂的搜索功能的后端,被广泛应用于日志和事件数据聚合、全文搜索、安全智能、业务分析等领域。以下是Elasticsearch的一些关键特点:
-
全文搜索:Elasticsearch非常擅长执行全文搜索,因为它建立在一个名为Lucene的全文搜索库之上。这使得它能够快速找到匹配特定查询的文档。
-
分布式和可扩展:Elasticsearch可以在多台服务器上运行,其数据可以分布在多个节点之间,从而提供高可用性和扩展性。
-
近实时操作:Elasticsearch能够在文档被索引后的短时间内(通常是一秒)使其可搜索,这使得它非常适合需要近实时搜索和分析的应用。
-
多种数据类型:它可以处理各种类型的数据,包括结构化文本、非结构化文本、地理位置、结构化日志数据等。
-
RESTful API:Elasticsearch提供了一个基于HTTP的RESTful API,通过这个API你可以执行搜索、插入、更新和删除操作,以及更复杂的查询。
-
灵活的查询语言:它支持一个功能强大的查询语言,允许执行和组合多种类型的搜索。
-
集成和扩展:Elasticsearch可以与多种工具和平台(如Kibana用于数据可视化、Logstash和Beats用于数据收集)集成,提供了一个完整的“Elastic Stack”解决方案。
Elasticsearch广泛用于日志收集、监控系统、搜索建议、数据分析等多种场景,特别是在需要处理和搜索大量数据的情况下。它的用户友好性和强大功能使其成为了企业和开发者中流行的选择。
今天,来学习下Elasticsearch 的典型查询方式,首先,预置一些基础数据。
一、精准查询term
1. term单值
在Elasticsearch中,精准查询(Term Query)是一种特殊的查询,它用于精确地搜索文档中的一个特定术语。这种查询类型是非常直接的:它要求字段中的值完全匹配指定的关键词,包括其大小写和全半角字符。这种查询通常用于过滤确切值,如状态代码、标识符、布尔值等。
-
特点
-
不分析:Term查询不会对查询字符串进行分析处理。这意味着它不会对查询条件进行分词,而是将整个字符串视为单个术语。
-
大小写敏感:因为不进行分析,所以Term查询对于大小写和特殊字符是敏感的。
-
精确匹配:只有当字段中的值与查询中的术语完全匹配时,文档才会被检索出来。
-
使用场景
-
检索某个确切值的文档,如特定用户ID、确切的产品代码或状态标志。
-
过滤具有特定关键字的记录,如日志文件中的错误代码。
-
示例
假设你有一个索引,其中包含多个文档,每个文档都有一个名为status
的字段。你想找到所有status
字段值为active
的文档。Term查询的代码示例如下:
{
"query": {
"term": {
"status": {
"value": "active"
}
}
}
}
这个查询将返回所有status
字段精确匹配字符串"active"
的文档。
- 注意
在使用Term查询时,需要确保查询的字段是不分析的(not_analyzed
)或者使用了关键字(keyword
)类型,这样才能实现精确匹配。如果字段被分析(例如,默认的text
类型字段),则可能需要使用其他查询类型,如match
查询。
2. terms多值
在Elasticsearch中,terms
查询是 term
查询的扩展版本,它允许你指定多个值来进行精准匹配。如果字段中的值与提供的任何一个术语匹配,文档就会被检索出来。这种查询类型非常适用于需要检索包含在指定列表中的任何值的场景。
-
特点
-
精确匹配:与
term
查询一样,terms
查询也是基于精确匹配。它不会对提供的术语进行分析处理。 -
多值匹配:可以指定一个值的列表,任何一个匹配都会导致文档被选中。
-
使用场景
-
在多个可能的值中检索文档,如多个用户ID、产品代码或状态。
-
当你有一个值的列表,并希望找到包含这些值中任何一个的文档时。
-
示例
假设你有一个包含用户信息的索引,每个文档都有一个名为user_id
的字段。你想找到user_id
为1
、2
或5
的所有文档。terms
查询的代码示例如下:
{
"query": {
"terms": {
"user_id": ["1", "2", "5"]
}
}
}
这个查询将返回所有user_id
字段值为"1"
、"2"
或"5"
的文档。
- 注意
在使用terms
查询时,同样需要注意字段的类型。如果字段是分析类型的(如text
类型),那么可能需要考虑其他查询方法或者确保字段有一个未分析(not_analyzed
)的子字段或关键字(keyword
)类型副本。在Elasticsearch中,通常一个字段会有一个原始的text
类型用于全文搜索,以及一个keyword
类型的副本用于精确匹配。
3. term多个字段
在Elasticsearch中,要对多个字段进行term
查询,通常会使用bool
查询的must
子句来组合多个term
查询。由于term
查询本身只针对一个字段,当你需要对多个字段进行精准匹配时,可以将多个term
查询放在bool
查询的must
数组中。
- 示例
假设你有一个索引,其中包含多个文档,每个文档都有field1
和field2
这两个字段。你想找到同时满足以下两个条件的文档:
field1
的值为value1
field2
的值为value2
对此,你可以构建一个如下的查询:
{
"query": {
"bool": {
"must": [
{
"term": {
"field1": "value1"
}
},
{
"term": {
"field2": "value2"
}
}
]
}
}
}
-
解释
-
bool
查询是一种复合查询类型,它允许你结合多个查询条件。 -
在
bool
查询中的must
子句表示所有列出的条件必须满足。 -
每个
term
查询针对一个字段进行精确匹配。 -
注意
-
确保查询的字段是不分析的(
not_analyzed
)或使用了keyword
类型,以确保精确匹配。 -
与单个
term
查询不同,这种组合查询允许你同时对多个字段应用精准匹配的条件。
通过这种方式,你可以轻松地在一个查询中针对多个字段进行精确的术语匹配,从而检索出满足所有条件的文档。
在Elasticsearch中,match
查询是一种常用的全文搜索查询,它会对查询字符串进行分析(tokenization和lowercasing等处理),然后在指定的字段上搜索这些分析后的词条。match
查询适用于那些需要全文搜索和对字段内容进行分词处理的场景。
二、match 查询
4.基本match
查询
match
查询用于在单个字段上执行全文搜索。以下是一个简单的match
查询示例:
{
"query": {
"match": {
"field_name": "search text"
}
}
}
在这个示例中,Elasticsearch会对"search text"
进行分析处理,并在field_name
字段中搜索匹配的词条。
5.match_all
查询
match_all
查询是一种特殊的查询,它会匹配索引中的所有文档。以下是一个match_all
查询的示例:
{
"query": {
"match_all": {}
}
}
这个查询对于获取索引中所有文档的概览很有用。
6.multi_match
查询
multi_match
查询允许你在多个字段上执行相同的全文搜索。以下是一个multi_match
查询的示例:
{
"query": {
"multi_match": {
"query": "search text",
"fields": ["field1", "field2"]
}
}
}
在这个示例中,Elasticsearch会在field1
和field2
中搜索"search text"
。
7. match_phrase
查询
match_phrase
查询用于搜索精确的短语,这意味着它会寻找所有词项按照给定顺序紧密排列的文档。以下是一个match_phrase
查询的示例:
{
"query": {
"match_phrase": {
"field_name": "exact phrase"
}
}
}
在这个示例中,只有那些包含了完整短语"exact phrase"
的文档才会被匹配。
8. match_phrase_prefix
查询
match_phrase_prefix
查询类似于match_phrase
查询,但它允许最后一个词项为前缀匹配。以下是一个match_phrase_prefix
查询的示例:
{
"query": {
"match_phrase_prefix": {
"field_name": "phrase pre"
}
}
}
在这个示例中,会匹配以"phrase pre"
开始的短语。
-
注意事项
-
确保你对字段类型和分析器有适当的了解,因为这些会影响搜索结果。
-
对于需要精确匹配的情况,考虑使用
term
查询而不是match
查询。 -
match
查询通常用于text
字段,而非keyword
字段。
9. wildcard模糊查询
在Elasticsearch中,wildcard
查询是一种模糊查询方法,它允许你在查询中使用通配符来匹配一个字段的值。这种查询类型适用于当你不确定确切的文本或者需要进行部分匹配时。通配符包括:
-
*
(星号):代表任何字符序列(包括零个字符)。 -
?
(问号):代表任何单个字符。 -
示例
假设你有一个名为 title
的字段,你想搜索包含某个模式的所有文档,可以使用以下wildcard
查询:
{
"query": {
"wildcard": {
"title": "te*t"
}
}
}
在这个示例中,查询会匹配title
字段中任何以te
开头,后跟任意字符序列,然后以t
结尾的文档。例如,它会匹配test
、text
、technical text
等。
如果你想匹配只有一个不确定字符的情况,可以使用?
:
{
"query": {
"wildcard": {
"title": "te?t"
}
}
}
这个查询会匹配test
和text
,但不会匹配technical text
,因为?
只代表一个单独的字符。
-
注意事项
-
性能问题:
wildcard
查询可能会导致性能问题,尤其是当通配符用在模式的开始部分时(例如*text
)。这是因为Elasticsearch必须扫描索引中的许多可能的项来找到匹配项。 -
适用场景:仅在确实需要时使用
wildcard
查询,并尽量将通配符放在模式的末尾。 -
字段类型:
wildcard
查询通常用于text
或keyword
类型的字段。对于text
字段,建议仔细考虑字段的分析方式,因为分析过程可能会影响wildcard
查询的匹配方式。
由于wildcard
查询可能对性能有显著影响,建议谨慎使用,并在可能的情况下寻找替代的查询方法。
三、bool查询
10.bool 查询
Elasticsearch 中的 bool
查询是一种复合查询,它允许你结合多个查询子句,并根据它们之间的逻辑关系(如 AND、OR 和 NOT)进行搜索。bool
查询主要包含以下四种类型的子句:
- must:子句必须匹配,等同于逻辑 AND。
- must_not:子句必须不匹配,等同于逻辑 NOT。
- should:至少有一个子句匹配,等同于逻辑 OR。在没有
must
子句时,至少一个should
子句必须匹配。 - filter:必须匹配,但它与
must
的不同之处在于它不影响得分(用于过滤)。
这是一个基本的 bool
查询示例:
GET /_search
{
"query": {
"bool": {
"must": [
{ "match": { "field1": "value1" } }
],
"filter": [
{ "term": { "field2": "value2" } }
],
"must_not": [
{ "range": { "field3": { "gte": 10, "lte": 20 } } }
],
"should": [
{ "term": { "field4": "value4" } },
{ "term": { "field5": "value5" } }
],
"minimum_should_match": 1
}
}
}
在这个示例中:
must
子句表示搜索结果必须匹配field1
字段的值为 "value1"。filter
子句用于过滤结果,这里是field2
字段的值必须为 "value2"。must_not
子句表示排除那些field3
字段的值在 10 到 20 之间的文档。should
子句包含两个条件,这意味着满足其中一个条件的文档将被视为匹配。这里,文档应包含field4
字段的值为 "value4" 或者field5
字段的值为 "value5"。minimum_should_match
指定至少应满足多少个should
子句。这里设置为 1,意味着至少一个should
子句应该匹配。
bool
查询非常灵活,可以组合多个条件来满足复杂的搜索需求。
四、filter查询
11. filter查询
在Elasticsearch中,filter
查询是一种特殊的查询方式,用于过滤文档,但与常规查询不同,它不影响搜索结果的相关性评分。filter
查询通常在bool
查询的filter
子句中使用,它可以提供快速的数据检索,因为Elasticsearch会对过滤条件进行缓存,从而提高重复查询的性能。
-
使用场景
-
当你只关心文档是否匹配查询条件,而不关心它们与查询的匹配程度如何时。
-
在聚合和统计数据时,因为这些操作通常不需要评分。
-
示例
以下是一个使用bool
查询中的filter
子句的示例:
{
"query": {
"bool": {
"must": {
"match": { "content": "elasticsearch" }
},
"filter": {
"term": { "status": "active" }
}
}
}
}
在这个查询中:
-
must
子句包含一个match
查询,它会计算相关性评分。 -
filter
子句包含一个term
查询,它用于过滤状态为active
的文档,但不影响评分。 -
更多过滤选项
filter
子句可以包含多种类型的查询,例如range
查询、terms
查询等:
{
"query": {
"bool": {
"filter": [
{ "range": { "date": { "gte": "2021-01-01", "lte": "2021-12-31" }}},
{ "terms": { "tags": ["elasticsearch", "search"] }}
]
}
}
}
在这个示例中,filter
子句结合了range
和terms
查询,用于找出在特定日期范围内,并且标签包含elasticsearch
或search
的文档。
-
注意事项
-
filter
查询不仅提高了查询效率,还可以节省系统资源,因为它不涉及评分计算。 -
由于Elasticsearch对
filter
子句的结果进行缓存,所以重复的过滤操作性能较高。 -
使用
filter
查询时,确保查询条件是精确的,以便获得最佳性能。
五、常见组合查询
12. bool-must-filter结合
结合 bool
、must
和 filter
来进行复合查询。
示例代码:
{
"query": {
"bool": {
"must": [
{ "match": { "field1": "value1" }}
],
"filter": [
{ "range": { "date": { "gte": "now-1d/d" }}}
]
}
}
}
13. bool-must
-should-match
使用 bool
、must
和 should
进行复合查询。
示例代码:
{
"query": {
"bool": {
"must": [
{ "match": { "field1": "value1" }}
],
"should": [
{ "match": { "field2": "value2" }}
]
}
}
}
14. bool-must-wildcard-range
结合 bool
、must
、wildcard
和 range
进行复合查询。
示例代码:
{
"query": {
"bool": {
"must": [
{ "wildcard": { "field1": "*pattern*" }},
{ "range": { "date": { "gte": "now-1d/d" }}}
]
}
}
}
在使用这些查询时,重要的是要根据你的具体需求和ElasticSearch索引的结构来调整查询条件。每种查询都有其特定的应用场景,了解它们如何工作和它们最适合的场景,将帮助你有效地使用ElasticSearch进行数据检索。