在 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"
}
}
}
}
}