个人技术分享

Elasticsearch教程之《一文读懂ES-DSL》

1. 什么是ES-DSL?

ES指Elasticsearch, DSL(Domain Specific Language):领域特定语言,DSL指的是专注于某个应用程序领域的计算机语言,又译作领域专用语言

Elasticsearch的查询DSL(查询领域特定语言)是一种JSON-based(基于JSON)的语法,它允许用户执行各种复杂的搜索操作,包括:

  • 全文搜索:对文本字段执行搜索,支持模糊匹配、短语搜索等。
  • 结构化搜索:在具有结构化数据的字段上执行搜索,例如日期、数字或枚举类型。
  • 复合查询:组合多个查询条件,如布尔查询,来精细化搜索结果。
  • 聚合:对数据进行聚合操作,以提取摘要统计信息或生成报告。
  • 排序:根据一个或多个字段对搜索结果进行排序。
  • 分页:使用fromsize参数来控制返回结果的数量和偏移量,实现数据的分页显示

以下是Elasticsearch查询DSL的一个简单示例,该查询搜索包含特定文本的文档,并指定返回结果的数量:

GET /my-index/_search
{
  "query": {
    "match": {
      "my_field": "search text"
    }
  },
  "size": 10
}

2. Query context和Filter context

一个查询字句的行为取决于它是用在query context 还是 filter context 中

  • **Query context **查询上下文:进行query context查询时,ES除了要判断某个文档是否与查询值匹配,还要计算相关度评分(relevance score),并放入到返回结果的_score字段中。

  • Filter context 过滤上下文:进行filter context查询时, 仅仅判断某个文档是否与查询值匹配,不但无需进行相关度评分的计算,而且对于高频率的filter查询,ES还会自动将查询结果缓存起来,以提高filter查询的性能。

参考官方文档

3. Query关键字

关键字 涵义
must 必须满足
must_not 必须不满足,在filter上下文中执行,不参与、不影响评分
filter 必须满足,但执行的是filter上下文,不参与、不影响评分
should
bool 在Elasticsearch中,bool查询是一个复合查询,它允许你组合多个查询条件,并使用布尔逻辑(AND、OR、NOT)来精细控制搜索结果

4. 什么是bool查询?

在Elasticsearch中,bool查询是一个复合查询,它允许你组合多个查询条件,并使用布尔逻辑(AND、OR、NOT)来精细控制搜索结果。bool查询非常有用,因为它提供了一种灵活的方式来构建复杂的查询,可以包含多个子句,每个子句都可以是不同的查询类型。

bool查询的主要功能

  1. 组合查询:将多个查询条件组合成一个单一的查询。
  2. 布尔逻辑:使用布尔运算符(mustshouldmust_notfilter)来指定查询逻辑。
    • must:子句中的所有条件都需要匹配,类似于AND逻辑,用于执行全文搜索或其他类型的查询。
    • should:至少一个条件需要匹配,类似于OR逻辑,通常与minimum_should_match参数一起使用,以指定必须匹配的最小条件数量。
    • must_not:子句中的条件都不应匹配,从搜索结果中排除匹配这些条件的文档。
    • filter:不涉及相关性得分的查询,用于结构化查询,如范围查询或存在性查询,通常用于过滤结果。
  3. 提高查询灵活性:通过组合不同类型的查询,可以创建复杂的搜索逻辑。

5. 查询示例

5.1. 单条件匹配

方法1:

GET /aliasName/_search?q=order_id:123456

方法2:

GET /aliasName/_search
{
  "query":{
    "bool":{
      "must":[
        {
          "match":{
            "order_id": "123456"
          }
        }
      ]
    }
  }
}

5.2. 多条件匹配(且)

GET /aliasName/_search?version=true
{
  "from": 0,
  "size": 500, 
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "status": "1"
          }
        },
        {
          "match": {
            "order_id":"123456"
          }
        }
      ]
    }
  }
}

5.3. 跨多个字段搜索文本multi_match

multi_match查询是一种强大的全文搜索查询,用于跨多个字段搜索文本。当您想要在一个查询中搜索多个字段,并且希望搜索词在这些字段中以相同的重要性出现时,multi_match查询非常有用。

**使用场景 **

  1. 跨字段搜索:当您想要在多个文本字段中搜索相同的文本,例如,在titledescriptionkeywords字段中搜索。
  2. 类型无关性multi_match查询会自动处理不同字段的文本类型,例如,它可以在text类型字段和keyword类型字段中搜索。
  3. 分析器应用:可以指定一个分析器来处理查询文本,以确保搜索词与索引时使用相同的分析器。
  4. 短语和模糊搜索:支持短语搜索和模糊匹配,适合对文本进行近似或拼写错误的搜索。
GET /aliasName/_search
{
  "query": {
    "multi_match": {
      "query": "Elasticsearch",
      "fields": ["title", "description"],
      "analyzer": "my_custom_analyzer"
    }
  }
}

5.4. 完全匹配term查询

term查询用于搜索与查询条件精确匹配的文档。这种查询对于处理未分析(not analyzed)的字段(如关键字字段)非常有效,它不会应用分析器,而是直接搜索精确值。

使用场景

  1. 精确匹配:当你需要找到与搜索词完全一致的文档时。
  2. 未分析字段:对于不经过分析器处理的字段,如keyword类型的字段。
  3. 数值和日期:搜索具体的数值和日期字段。
  4. 布尔值:搜索布尔类型的字段,如truefalse
POST /aliasName/_search
{
  "query": {
    "term" : { "user" : "foo1" } 
  }
}

5.5. 范围查询

关键字 涵义
gte 大于等于
gt 大于
lte 小于等于
lt 小于
boost 查询权重
 GET /aliasName/_search
{
    "query": {
        "range": {
          "create_time": {
            "gte": 1614185651000,
            "lt": 1648716851000
          }
        }
    }
}

5.6. 指定字段不为空

例如:返回user字段存在值的记录,默认情况下只有字段的值为null或者[]的时候,elasticsearch才会认为字段不存在;

GET /aliasName/_search
{
    "query": {
        "exists" : { 
        	"field" : "user" 
        }
    }
}

5.7. 前缀查询

GET /aliasName/_search
{ "query": {
    "prefix" : { 
    	"user" : "张" 
    }
  }
}

5.8. 通配符查询,wildcard query

类似MySQL中的like, 其中?代表任意一个字符*代表任意的一个或多个字符

#模糊查询,比如查询李世民
GET /aliasName/_search
{
    "query": {
        "wildcard" : { 
        	"user" : "李*" 
        }
    }
}

如果不想对字段内容进行分词查询的话可以将内容变成keyword模式去查询

#模糊查询,比如查询李世民
GET /aliasName/_search
{
		"query": {
    	"wildcard":{
      	"senderName.keyword": "李*"
    	}
		}
}

5.9. 正则查询

注意: regexp(正则表达式)查询的性能很大程度上取决于所选的正则表达式。匹配一切像 “.*”,是非常慢的,使用回顾正则表达式也是如此。如果可能,您应该尝试在正则表达式开始之前使用长前缀。通配符匹配器**“.*?+”**将主要降低性能。

GET /aliasName/_search
{
    "query": {
        "regexp":{
            "name.first": "s.*y"
        }
    }
}

5.10 模糊查询之Fuzzy 查询

模糊查询生成在模糊性中指定的最大编辑距离内的所有可能的匹配项,然后检查项词典以找出实际存在于索引中的那些项

GET /aliasName/_search
{
    "query": {
       "fuzzy" : { "user" : "ki" }
    }
}

更多详情请看

5.11 或Should查询

使用场景

  1. 多条件搜索:当你想要搜索包含多个可能条件中的任意一个的文档时。
  2. 提高召回率:在不希望过于严格限制搜索结果时,使用"或"查询可以增加搜索结果的数量。
GET /aliasName/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "Elasticsearch"
          }
        },
        {
          "match": {
            "content": "Search"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

在这个示例中:

  • bool查询的should数组包含了两个match查询,分别搜索titlecontent字段。
  • minimum_should_match参数指定了必须满足的最低条件数量。在这个例子中,设置为1表示文档需要至少满足一个should条件。

特点

  • should子句中的查询条件使用"或"逻辑进行组合。
  • 可以通过minimum_should_match参数控制必须满足的查询条件数量,这对于调整查询的宽松程度很有用。

5.12 in和not in查询

ES中如何实现in和not in查询

ES中可以通过terms进行多值匹配查询,实现in和not in查询逻辑。

in查询
GET /aliasName/_search
"query": {
    "terms": {
      "name": [
        "老万", "小明"
      ]
    }
}

not in查询
GET /aliasName/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "terms": {
              "name": [
                "老万","小明"
              ]
          }
        }
      ]
    }
  }
}

5. term和match区别

在Elasticsearch中,term查询和match查询是两种不同的查询方式,它们在搜索行为和使用场景上有所区别:

  1. 查询类型

    • term查询:用于搜索未分析(unanalyzed)字段的精确值。它不会应用任何文本分析器,直接匹配字段中的原始值。
    • match查询:用于搜索经过分析(analyzed)字段的文本。它使用分析器将查询文本转换为词项,然后搜索这些词项。
  2. 使用场景

    • term查询:适用于搜索关键字、标签、状态代码等不需要分析的字段。
    • match查询:适用于搜索全文文本,如文章内容、产品描述等。
  3. 分析器

    • term查询:不使用分析器,对大小写敏感,只搜索精确的词条。
    • match查询:使用分析器,可以处理大小写不敏感、同义词扩展等。
  4. 搜索行为

    • term查询:执行精确匹配,返回包含确切词条的文档。
    • match查询:执行全文搜索,可以返回包含查询词项或其变体的文档。
  5. 数据类型

    • term查询:通常用于keyword类型的字段。
    • match查询:通常用于text类型的字段。
  6. 查询语法

    • term查询:直接使用词条作为查询值。
    • match查询:可以使用单个词或短语作为查询值。
  7. 性能

    • term查询:因为不涉及分析过程,通常更快。
    • match查询:由于涉及分析过程,可能会稍慢一些。
  8. 搜索结果

    • term查询:返回的文档包含与查询条件完全一致的字段值。
    • match查询:返回的文档可能包含查询词项的相关词或短语。

示例:

假设有一个名为my-index的索引,包含一个product文档类型,其中有nametext类型)和categorykeyword类型)字段。

  • 使用match查询搜索name字段:

    GET /aliasName/_search
    {
      "query": {
        "match": {
          "name": "Elasticsearch book"
        }
      }
    }
    
  • 使用term查询搜索category字段:

    GET /aliasName/_search
    {
      "query": {
        "term": {
          "category": "books"
        }
      }
    }
    

在这些示例中,match查询会在name字段中搜索包含"Elasticsearch book"这个短语的文档,而term查询会在category字段中搜索精确值为"books"的文档。

了解termmatch查询的区别有助于你根据具体的搜索需求选择合适的查询方式。

6. 删除指定数据

POST /aliasName/_delete_by_query
{
  "query":{
    "bool":{
      "must":[
        {
          "match":{
            "order_id": "123456789"
          }
        }
      ]
    }
  }
}