在 Elasticsearch 中,查询可以通过几种不同的语法种类来编写和执行,这些语法种类适用于不同的应用场景和用户需求。下面是 Elasticsearch 支持的主要查询语法种类:

查询种类

  • DSL
  • Simple Query String
  • URI Search
  • SQL
  • Script Query

字段类型

正确地定义字段类型(或称为数据类型)是确保数据正确存储和查询的关键。

创建索引时定义字段类型

在创建索引时,你可以通过映射定义来指定每个字段的类型。映射可以指定诸如字段的数据类型、是否被索引、分析器设置等属性。

curl -X PUT "http://localhost:9200/my_index" -H "Content-Type: application/json" -d'
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "email": {
        "type": "keyword"
      },
      "birthday": {
        "type": "date",
        "format": "yyyy-MM-dd"
      },
      "location": {
        "type": "geo_point"
      }
    }
  }
}'

注意:

  • 一旦索引被创建并定义了映射,某些字段的类型就不能更改(例如,不能将一个已经是 integer 类型的字段更改为 text)。如果需要更改字段类型,通常需要创建一个新的索引并将数据重新索引到新的索引中。
  • 映射定义一旦设置,就会影响 Elasticsearch 如何索引和搜索那些字段,因此在设计映射时需要仔细考虑。

文本类型 (Text)

用于全文搜索。这种类型的字段会被分析(analyzed),即文本会被分解成一系列的单词或词语,以便进行全文搜索。

用途: 存储需要被搜索的数据,如文章内容、产品描述等。

例子"description": { "type": "text" }

关键字类型 (Keyword)

Keyword: 用于精确值搜索。这种类型的字段不会被分析,整个字符串会被作为一个单独的词元来索引。

用途: 适合用于索引结构化的内容,如邮箱地址、标签、状态码等。

例子"status": { "type": "keyword" }

数值类型

  • Integer: 整数类型。
  • Long: 较大整数。
  • Short: 较小整数。
  • Byte: 最小整数类型。
  • Double: 双精度浮点数。
  • Float: 单精度浮点数。
  • Half Float: 半精度浮点数。
  • Scaled Float: 缩放的浮点数,适用于精确的小数。
    • 用途: 存储数值数据,用于数值计算和范围查询。
    • 例子"price": { "type": "double" }

日期类型 (Date)

Date: 表示日期和时间,可以自定义格式

用途: 存储日期和时间,用于时间查询和聚合

例子"timestamp": { "type": "date" }

布尔类型 (Boolean)

例子"active": { "type": "boolean" }

二进制类型 (Binary)

Binary: 用于存储二进制数据,不可搜索

用途: 存储编码的数据,如图片的编码。

例子"blob": { "type": "binary" }

范围类型 (Range Types)

Integer Range, Float Range, Long Range, Double Range, Date Range: 这些类型用于存储数值或日期的范围。

用途: 用于存储价格区间、日期区间等。

例子"date_range": { "type": "date_range" }

Query DSL

Elasticsearch 的查询 DSL(Domain Specific Language)是最强大和最灵活的查询方式。它是一个基于 JSON 的语言,允许用户构建复杂的查询和聚合。查询 DSL 提供了广泛的查询类型,如全文查询、术语级查询、复合查询等。

{
  "query": {
    "match": {
      "field_name": "text to search"
    }
  }
}

基本结构

  • query: 包含所有的查询条件,可以是简单的查询也可以是复杂的布尔查询。
  • aggs (或 aggregations): 用于执行数据聚合操作,如计算平均值、最大值、分组等。
  • sort: 定义如何对结果进行排序。
  • from 和 size: 用于分页处理,from 定义从哪一条记录开始获取,size 定义获取多少条记录。
  • fields: 指定返回哪些字段。

查询类型

全文搜索 (Full Text Queries)

Match Query: 最基本的全文查询,对字段进行分析后查询。例如,查找描述中包含“快乐”的文档:

{
  "query": {
    "match": {
      "description": "快乐"
    }
  }
}

Multi Match Query: 在多个字段上执行全文搜索。例如,同时在标题和描述中搜索:

{
  "query": {
    "multi_match": {
      "query": "搜索文本",
      "fields": ["title", "description"]
    }
  }
}

Match Phrase Query: 搜索与指定短语匹配的文档,保持词语的相对位置

{
  "query": {
    "match_phrase": {
      "description": "快乐 学习"
    }
  }
}

术语级查询 (Term Level Queries)

Term Query: 对精确值进行匹配,不分析查询字符串

{
  "query": {
    "term": {
      "status": {
        "value": "active"
      }
    }
  }
}

Range Query: 查找字段值在指定范围内的文档。

{
  "query": {
    "range": {
      "age": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}

Exists Query: 查找指定字段有值的文档

{
  "query": {
    "exists": {
      "field": "username"
    }
  }
}

复合查询 (Compound Queries)

Bool Query: 将多个查询条件以逻辑方式组合(must, should, must_not, filter)

{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "搜索" }},
        { "match": { "description": "Elasticsearch" }}
      ],
      "filter": [
        { "term": { "status": "active" }}
      ],
      "must_not": [
        { "range": { "age": { "lte": 18 }}}
      ]
    }
  }
}

聚合

聚合用于对数据进行统计分析,如计算总数、平均值、分组等。

Terms Aggregation: 按字段值分组

{
  "aggs": {
    "group_by_status": {
      "terms": { "field": "status" }
    }
  }
}

排序与分页

{
  "sort": [
    { "post_date": { "order": "desc" }},
    { "user": { "order": "asc" }}
  ]
}
{
  "from": 0,
  "size": 10
}

调整权重(Boosting)

可以通过增加权重来提高某些查询条件的优先级。在 Elasticsearch 中,可以使用 boost 参数来实现这一点

{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": "Elasticsearch",
            "boost": 2.0
          }
        },
        {
          "match": {
            "content": "Elasticsearch"
          }
        }
      ]
    }
  }
}

Elasticsearch SQL

从 Elasticsearch 6.3 版本开始,Elasticsearch 提供了 SQL 查询支持,允许用户使用 SQL 语法来查询 Elasticsearch,这对于熟悉 SQL 语法的用户来说非常方便,无需专门学习 Elasticsearch 的查询 DSL (Domain Specific Language)也能上手查询。

POST /_sql?format=txt
{
  "query": "SELECT * FROM index_name WHERE condition"
}

要在Elasticsearch中启用和使用SQL功能,你需要安装X-Pack插件。X-Pack插件包含了许多扩展功能,包括SQL接口。安装完成后,需要在Elasticsearch配置文件中启用X-Pack插件,并重启Elasticsearch服务。

# 安装X-Pack插件
./bin/elasticsearch-plugin install x-pack

# 启用X-Pack插件
# 在elasticsearch.yml配置文件中添加以下配置
xpack.sql.enabled: true

在启用SQL功能后,你可以通过REST API、命令行工具或JDBC驱动来执行SQL查询。Elasticsearch SQL的语法与标准的SQL语法非常相似,支持SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY等常见SQL语句。

语法

SELECT select_expr [, ...]
[ FROM table_name ]
[ WHERE condition ]
[ GROUP BY grouping_element [, ...] ]
[ HAVING condition]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ LIMIT [ count ] ]
[ PIVOT ( aggregation_expr FOR column IN ( value [ [ AS ] alias ] [, ...] ) ) ]

将SQL转换为DSL


GET /_sql/translate
{
"query":"SELECT * FROM es_order limit 1"
}

当使用MATCH或QUERY函数时,会启用全文搜索功能,SCORE函数可以用来统计搜索评分。


GET /_sql?format=txt
{
"query":"select * from es_order where MATCH(address, '武汉') or MATCH(productType, '手机') limit 10"
}

注意:

  • Elasticsearch SQL 不完全支持所有 SQL 功能,特别是那些高度依赖关系型数据模型的功能。
  • 性能问题:虽然 Elasticsearch SQL 在处理搜索和聚合查询时非常高效,但在处理大规模的 JOIN 操作或非常复杂的关系查询时可能不如传统的关系数据库性能高。

简单查询字符串 (Simple Query String)

这种查询语法允许用户使用简单的语法来执行全文搜索,它支持一些基本的运算符,如 +(必须包含)、-(必须不包含)、|(或)和 *(通配符)。

{
  "query": {
    "simple_query_string": {
       "query": "this | that -other"
    }
  }
}

URI 搜索 (URI Search)

URI 搜索允许通过 HTTP 请求的 URI 来传递查询参数。这种方式简单且易于使用,适合简单的搜索需求,但不支持复杂查询。

GET /_search?q=field_name:text+to+search

脚本查询 (Script Query)

在某些情况下,标准的查询 DSL 不足以表达复杂的逻辑或计算需求。Elasticsearch 允许使用 Painless 脚本或其他脚本语言(如 JavaScript、Python,但这些通常需要额外的插件)来编写更复杂的查询。

{
  "query": {
    "bool": {
      "must": {
        "script": {
          "script": "doc['field_name'].value > 10"
        }
      }
    }
  }
}