【全面详解】ElasticSearch 常见的14种查询大全代码示例

ElasticSearch 常见的查询大全,以及代码示例

Elasticsearch 简介

Elasticsearch 是一个高度可扩展的开源全文搜索和分析引擎,允许你以近实时的方式存储、搜索和分析大量数据。它通常用于复杂的搜索功能的后端,被广泛应用于日志和事件数据聚合、全文搜索、安全智能、业务分析等领域。以下是Elasticsearch的一些关键特点:

  1. 全文搜索:Elasticsearch非常擅长执行全文搜索,因为它建立在一个名为Lucene的全文搜索库之上。这使得它能够快速找到匹配特定查询的文档。

  2. 分布式和可扩展:Elasticsearch可以在多台服务器上运行,其数据可以分布在多个节点之间,从而提供高可用性和扩展性。

  3. 近实时操作:Elasticsearch能够在文档被索引后的短时间内(通常是一秒)使其可搜索,这使得它非常适合需要近实时搜索和分析的应用。

  4. 多种数据类型:它可以处理各种类型的数据,包括结构化文本、非结构化文本、地理位置、结构化日志数据等。

  5. RESTful API:Elasticsearch提供了一个基于HTTP的RESTful API,通过这个API你可以执行搜索、插入、更新和删除操作,以及更复杂的查询。

  6. 灵活的查询语言:它支持一个功能强大的查询语言,允许执行和组合多种类型的搜索。

  7. 集成和扩展: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_id125的所有文档。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数组中。

  • 示例

假设你有一个索引,其中包含多个文档,每个文档都有field1field2这两个字段。你想找到同时满足以下两个条件的文档:

  • 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会在field1field2中搜索"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结尾的文档。例如,它会匹配testtexttechnical text等。

如果你想匹配只有一个不确定字符的情况,可以使用?

{
  "query": {
    "wildcard": {
      "title": "te?t"
    }
  }
}

这个查询会匹配testtext,但不会匹配technical text,因为?只代表一个单独的字符。

  • 注意事项

  • 性能问题wildcard查询可能会导致性能问题,尤其是当通配符用在模式的开始部分时(例如*text)。这是因为Elasticsearch必须扫描索引中的许多可能的项来找到匹配项。

  • 适用场景:仅在确实需要时使用wildcard查询,并尽量将通配符放在模式的末尾。

  • 字段类型wildcard查询通常用于textkeyword类型的字段。对于text字段,建议仔细考虑字段的分析方式,因为分析过程可能会影响wildcard查询的匹配方式。

由于wildcard查询可能对性能有显著影响,建议谨慎使用,并在可能的情况下寻找替代的查询方法。

三、bool查询

10.bool 查询

Elasticsearch 中的 bool 查询是一种复合查询,它允许你结合多个查询子句,并根据它们之间的逻辑关系(如 AND、OR 和 NOT)进行搜索。bool 查询主要包含以下四种类型的子句:

  1. must:子句必须匹配,等同于逻辑 AND。
  2. must_not:子句必须不匹配,等同于逻辑 NOT。
  3. should:至少有一个子句匹配,等同于逻辑 OR。在没有 must 子句时,至少一个 should 子句必须匹配。
  4. 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子句结合了rangeterms查询,用于找出在特定日期范围内,并且标签包含elasticsearchsearch的文档。

  • 注意事项

  • filter查询不仅提高了查询效率,还可以节省系统资源,因为它不涉及评分计算。

  • 由于Elasticsearch对filter子句的结果进行缓存,所以重复的过滤操作性能较高。

  • 使用filter查询时,确保查询条件是精确的,以便获得最佳性能。

五、常见组合查询

12. bool-must-filter结合

结合 boolmustfilter 来进行复合查询。

示例代码

{
  "query": {
    "bool": {
      "must": [
        { "match": { "field1": "value1" }}
      ],
      "filter": [
        { "range": { "date": { "gte": "now-1d/d" }}}
      ]
    }
  }
}

13. bool-must

-should-match
使用 boolmustshould 进行复合查询。

示例代码

{
  "query": {
    "bool": {
      "must": [
        { "match": { "field1": "value1" }}
      ],
      "should": [
        { "match": { "field2": "value2" }}
      ]
    }
  }
}

14. bool-must-wildcard-range

结合 boolmustwildcardrange 进行复合查询。

示例代码

{
  "query": {
    "bool": {
      "must": [
        { "wildcard": { "field1": "*pattern*" }},
        { "range": { "date": { "gte": "now-1d/d" }}}
      ]
    }
  }
}

在使用这些查询时,重要的是要根据你的具体需求和ElasticSearch索引的结构来调整查询条件。每种查询都有其特定的应用场景,了解它们如何工作和它们最适合的场景,将帮助你有效地使用ElasticSearch进行数据检索。