2023-12-11
中间件
0

目录

什么是 Query DSL?
数据建模起源:索引与映射(Mapping)
索引(Index)基础概念与操作
映射(Mapping)深度解析
映射的概念与作用
动态映射 vs 显式映射
映射参数详解
字段数据类型全面指南
核心数据类型
文本类型(Text)
关键字类型(Keyword)
数值类型
日期类型(Date)
布尔类型(Boolean)
二进制类型(Binary)
复杂数据类型
对象类型(Object)
嵌套类型(Nested)
数组类型(Array)
地理数据类型
专用数据类型
多字段(Multi-fields)映射
多字段概念
多字段使用场景
基础查询:精准匹配与全文搜索
精准匹配查询(Term-level Queries)
term 查询 - 精确值匹配
terms 查询 - 多值精确匹配
range 查询 - 范围查询
exists 查询 - 存在性检查
prefix 查询 - 前缀匹配
全文搜索查询(Full-text Queries)
match 查询 - 标准全文搜索
match_phrase 查询 - 短语匹配
multi_match 查询 - 多字段搜索
复合查询:构建复杂的搜索逻辑
bool 查询 - 布尔组合查询
constant_score 查询 - 恒定评分查询
实战案例:电商商品搜索
问题一
问题二
Java 代码示例
总结

对于任何想要掌握 Elasticsearch 的开发者来说,Query DSL(Domain Specific Language)都是必须征服的核心领域。本文作为系列第一篇,将深入解析基础查询和复合查询,帮助你构建精准的搜索条件。

什么是 Query DSL?

在开始具体查询之前,我们先理解什么是 Query DSL。

DSL(Domain Specific Language) 是专门针对特定领域的语言。Elasticsearch 的 Query DSL 是一个基于 JSON 的、丰富的查询语言,它允许你构建复杂的搜索条件,从简单的关键词匹配到复杂的多条件组合查询。

与传统的 SQL 相比,DSL 提供了更强大、更灵活的搜索能力:

sql
-- SQL 方式 SELECT * FROM products WHERE (name LIKE '%手机%' OR description LIKE '%手机%') AND price BETWEEN 1000 AND 3000 AND category = 'electronics'; -- Elasticsearch DSL 方式(等价) { "query": { "bool": { "must": [ { "match": { "name": "手机" } } ], "should": [ { "match": { "description": "手机" } } ], "filter": [ { "range": { "price": { "gte": 1000, "lte": 3000 } } }, { "term": { "category": "electronics" } } ] } } }

数据建模起源:索引与映射(Mapping)

索引和映射是Elasticsearch数据建模的核心

索引(Index)基础概念与操作

在Elasticsearch中,索引是文档的集合,类似于关系型数据库中的"数据库"概念。每个索引包含一组具有相似特征的文档,并拥有独立的配置和映射。

核心特性:

  • 分布式存储:索引数据分布在多个分片上

  • 水平扩展:可通过增加分片实现容量扩展

  • 独立配置:每个索引可独立设置映射、分片数、副本数等

索引的基本操作

创建索引:

json
PUT /my_first_index { "settings": { "number_of_shards": 3, "number_of_replicas": 2, "refresh_interval": "1s" } }

查看索引信息:

json
GET /my_first_index // 返回结果示例 { "my_first_index": { "aliases": {}, "mappings": {}, "settings": { "index": { "creation_date": "1627896531000", "number_of_shards": "3", "number_of_replicas": "2", "uuid": "abc123...", "version": {"created": "7100099"}, "provided_name": "my_first_index" } } } }

删除索引:

json
DELETE /my_first_index

索引状态管理:

json
// 关闭索引(不可写入和搜索,但数据保留) POST /my_first_index/_close // 打开索引 POST /my_first_index/_open // 清空索引数据(保留索引结构) POST /my_first_index/_delete_by_query { "query": { "match_all": {} } }

映射(Mapping)深度解析

映射的概念与作用

映射是Elasticsearch中的模式定义,它定义了:

  • 字段的数据类型

  • 字段的索引方式

  • 字段的分析器配置

  • 字段的存储选项

动态映射 vs 显式映射

动态映射(Dynamic Mapping)

Elasticsearch自动推断字段类型:

json
// 创建索引,启用动态映射 PUT /dynamic_mapping_demo { "mappings": { "dynamic": true // 默认值 } } // 插入文档,ES自动推断字段类型 POST /dynamic_mapping_demo/_doc { "title": "Elasticsearch Guide", // 推断为text "views": 150, // 推断为long "price": 29.99, // 推断为float "published": true, // 推断为boolean "publish_date": "2023-01-15", // 推断为date "tags": ["search", "database"] // 推断为text[] }

动态映射规则:

JSON数据类型Elasticsearch数据类型
stringtext + keyword子字段
integerlong
floatfloat
booleanboolean
datedate
array根据第一个元素类型推断
objectobject

显式映射(Explicit Mapping)

手动定义所有字段类型,推荐生产环境使用:

json
PUT /explicit_mapping_demo { "mappings": { "dynamic": "strict", // 禁止未定义的字段 "properties": { "title": { "type": "text", "analyzer": "standard" }, "views": { "type": "integer" } // 其他字段定义... } } }

dynamic 参数选项:

  • true:自动检测并添加新字段(默认)

  • false:忽略新字段(不索引但存储在_source)

  • strict:遇到未映射字段时拒绝文档(推荐)

映射参数详解

核心映射参数

type - 字段数据类型:

json
"title": { "type": "text" }

index - 控制字段是否被索引:

json
"internal_id": { "type": "keyword", "index": false // 不索引,无法搜索但可聚合 }

store - 独立存储字段值:

json
"content": { "type": "text", "store": true // 独立于_source存储 }

doc_values - 列式存储,用于排序和聚合:

json
"price": { "type": "float", "doc_values": true // 默认开启 }

norms - 存储长度归一化因子,影响评分:

json
"description": { "type": "text", "norms": false // 不需要评分时关闭,节省空间 }

null_value - 替换空值:

json
"category": { "type": "keyword", "null_value": "unknown" // null替换为"unknown" }

copy_to - 复制字段值到自定义_all字段:

json
"first_name": { "type": "text", "copy_to": "full_name" }, "last_name": { "type": "text", "copy_to": "full_name" } // 搜索full_name字段可同时匹配first_name和last_name

文本字段专用参数

analyzer - 索引时分析器:

json
"content": { "type": "text", "analyzer": "ik_max_word" // 中文细粒度分词 }

search_analyzer - 搜索时分析器:

json
"content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" // 搜索时粗粒度分词 }

fielddata - 内存中字段数据(慎用):

json
"tags": { "type": "text", "fielddata": true // 允许对text字段聚合,消耗大量内存 }

字段数据类型全面指南

核心数据类型

文本类型(Text)

用于全文搜索的字符串:

json
PUT /text_demo { "mappings": { "properties": { "title": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } }

关键字类型(Keyword)

用于精确值匹配:

json
"status": { "type": "keyword", "ignore_above": 256, // 超过长度不索引 "normalizer": "lowercase" // 标准化处理 }

数值类型

类型范围存储大小使用场景
long-2⁶³ to 2⁶³-164-bit大整数计数
integer-2³¹ to 2³¹-132-bit一般整数
short-32,768 to 32,76716-bit小范围数值
byte-128 to 1278-bit状态码
double64-bit双精度64-bit科学计算
float32-bit单精度32-bit一般小数
half_float16-bit半精度16-bit节省空间
scaled_float缩放浮点可变金融数据
json
"metrics": { "properties": { "price": { "type": "scaled_float", "scaling_factor": 100 // 存储为整数,节省空间 }, "quantity": { "type": "integer" }, "rating": { "type": "half_float" } } }

日期类型(Date)

json
"timestamps": { "properties": { "create_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||epoch_millis" }, "update_time": { "type": "date", "format": "strict_date_optional_time" } } }

支持的日期格式:

  • epoch_millis:时间戳毫秒数

  • yyyy-MM-dd:基本日期格式

  • yyyy-MM-dd HH:mm

    :自定义格式

  • strict_date_optional_time:严格模式

布尔类型(Boolean)

json
"flags": { "properties": { "is_published": { "type": "boolean" }, "is_deleted": { "type": "boolean", "null_value": false // null视为false } } }

二进制类型(Binary)

存储Base64编码的二进制数据:

json
"attachment": { "type": "binary", "doc_values": false, "store": true }

复杂数据类型

对象类型(Object)

处理JSON对象:

json
PUT /object_demo { "mappings": { "properties": { "user": { "type": "object", "properties": { "name": {"type": "text"}, "age": {"type": "integer"} } } } } } // 插入文档 POST /object_demo/_doc { "user": { "name": "张三", "age": 30 } }

嵌套类型(Nested)

保持数组对象的独立性:

json
PUT /nested_demo { "mappings": { "properties": { "products": { "type": "nested", "properties": { "name": {"type": "keyword"}, "price": {"type": "float"} } } } } } // 嵌套查询示例 GET /nested_demo/_search { "query": { "nested": { "path": "products", "query": { "bool": { "must": [ {"term": {"products.name": "手机"}}, {"range": {"products.price": {"gte": 1000}}} ] } } } } }

数组类型(Array)

Elasticsearch没有专门的数组类型,任何字段都可以包含多个值:

json
"tags": { "type": "keyword" // 可以存储单个值或多个值 } // 插入数组数据 POST /array_demo/_doc { "tags": ["搜索", "数据库", "NoSQL"] // 自动处理为数组 }

地理数据类型

地理点(Geo-point)

存储经纬度坐标:

json
PUT /geo_demo { "mappings": { "properties": { "location": { "type": "geo_point" } } } } // 多种格式支持 POST /geo_demo/_doc { "location": { "lat": 40.7128, "lon": -74.0060 } } POST /geo_demo/_doc { "location": "40.7128,-74.0060" // 字符串格式 } POST /geo_demo/_doc { "location": [ -74.0060, 40.7128 ] // 数组格式[经度,纬度] }

地理查询示例:

json
GET /geo_demo/_search { "query": { "geo_distance": { "distance": "10km", "location": { "lat": 40.7128, "lon": -74.0060 } } } }

地理形状(Geo-shape)

存储复杂地理形状:

json
"boundary": { "type": "geo_shape", "strategy": "recursive" } // 插入多边形数据 POST /geo_shape_demo/_doc { "boundary": { "type": "polygon", "coordinates": [[ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]] } }

专用数据类型

IP类型(IP)

存储IPv4和IPv6地址:

json
"client_ip": { "type": "ip" } // 范围查询示例 GET /logs/_search { "query": { "range": { "client_ip": { "gte": "192.168.1.1", "lte": "192.168.1.254" } } } }

完成建议类型(Completion)

用于自动完成功能:

json
"suggest": { "type": "completion", "analyzer": "simple", "preserve_separators": true, "preserve_position_increments": true, "max_input_length": 50 } // 使用示例 POST /suggestion_demo/_doc { "suggest": { "input": ["elasticsearch", "elastic"], "weight": 10 } }

令牌计数类型(Token count)

统计分词后的词条数量:

json
"content": { "type": "text", "fields": { "word_count": { "type": "token_count", "analyzer": "standard" } } }

排名特征类型(Rank features)

用于学习排名(Learning to Rank):

json
"features": { "type": "rank_features" } // 插入数据 POST /ranking_demo/_doc { "features": { "query_length": 10.5, "pagerank": 8.2, "url_length": 3.0 } }

多字段(Multi-fields)映射

多字段概念

多字段允许为同一内容以不同方式索引,实现不同搜索需求:

json
PUT /multi_field_demo { "mappings": { "properties": { "title": { "type": "text", "analyzer": "ik_max_word", // 主字段:中文分词 "fields": { "keyword": { "type": "keyword", // 子字段:精确匹配 "ignore_above": 256 }, "english": { "type": "text", // 子字段:英文分词 "analyzer": "english" }, "raw": { "type": "text", // 子字段:不分词 "analyzer": "keyword" } } } } } }

多字段使用场景

不同搜索方式:

json
// 使用主字段进行全文搜索 GET /multi_field_demo/_search { "query": { "match": { "title": "搜索引擎" } } } // 使用keyword字段进行精确匹配 GET /multi_field_demo/_search { "query": { "term": { "title.keyword": "Elasticsearch指南" } } } // 使用english字段进行英文搜索 GET /multi_field_demo/_search { "query": { "match": { "title.english": "search engine" } } }

基础查询:精准匹配与全文搜索

Elasticsearch 查询主要分为两大类:精准匹配(Term-level) 和 全文搜索(Full-text)。

精准匹配查询(Term-level Queries)

精准匹配查询用于查找完全匹配指定值的文档,不进行分词分析。主要用于 keyword、date、integer 等确切值字段。

term 查询 - 精确值匹配

查找在指定字段中包含确切术语的文档。

json
// 查找 category 字段精确等于 "electronics" 的商品 GET /products/_search { "query": { "term": { "category": { "value": "electronics" } } } }

注意

对于 text 类型字段,使用 term 查询时需要小心。因为 text 字段会被分词,而 term 查询不会对搜索词进行分词。例如,搜索 "smart phone" 可能无法匹配到被分词为 ["smart", "phone"] 的文档。

terms 查询 - 多值精确匹配

查找指定字段匹配任意一个给定值的文档。

json
// 查找 category 为 "electronics" 或 "books" 的商品 GET /products/_search { "query": { "terms": { "category": ["electronics", "books"] } } }

range 查询 - 范围查询

查找指定字段在某个范围内的文档。

json
// 查找价格在 1000 到 3000 之间,且上架时间在 2023年之后的商品 GET /products/_search { "query": { "range": { "price": { "gte": 1000, "lte": 3000 } } } }

范围操作符:

  • gte:大于等于(≥)

  • gt:大于(>)

  • lte:小于等于(≤)

  • lt:小于(<)

对于日期字段,还支持相对时间:

json
{ "range": { "publish_date": { "gte": "now-7d/d", // 7天前到现在 "lte": "now" } } }

exists 查询 - 存在性检查

查找包含指定字段的文档(字段值不为 null 或空数组)。

json
// 查找有描述信息的商品 GET /products/_search { "query": { "exists": { "field": "description" } } }

prefix 查询 - 前缀匹配

查找指定字段以给定前缀开头的文档。

json
// 查找名称以 "smart" 开头的商品 GET /products/_search { "query": { "prefix": { "name": "smart" } } }

全文搜索查询(Full-text Queries)

全文搜索查询用于在 text 字段上执行全文搜索,会考虑分词和相关性评分。

match 查询 - 标准全文搜索

最常用的全文搜索查询,会对搜索词进行分词,然后查找包含任何分词结果的文档。

json
// 搜索包含 "智能手机" 的商品 GET /products/_search { "query": { "match": { "description": "智能手机" } } }

搜索过程:

  • 搜索词 "智能手机" 被 IK 分词器分成:["智能", "手机"]

  • 查找 description 字段包含 "智能" 或 "手机" 的文档

  • 根据相关性评分(_score)对结果排序

match_phrase 查询 - 短语匹配

查找包含完整短语的文档,分词顺序必须完全匹配。

json
// 搜索包含完整短语 "智能手机" 的商品 GET /products/_search { "query": { "match_phrase": { "description": "智能手机" } } }

slop 参数:允许短语间有一定间隔

json
{ "query": { "match_phrase": { "description": { "query": "智能 手机", "slop": 2 // 允许词语间最多间隔2个词 } } } }

multi_match 查询 - 多字段搜索

在多个字段上执行相同的 match 查询。

json
// 在 name 和 description 字段中搜索 "手机" GET /products/_search { "query": { "multi_match": { "query": "手机", "fields": ["name", "description"] } } }

字段加权:

json
{ "multi_match": { "query": "手机", "fields": ["name^3", "description"] // name字段的权重是description的3倍 } }

复合查询:构建复杂的搜索逻辑

复合查询允许你将多个查询组合起来,构建复杂的搜索逻辑。

bool 查询 - 布尔组合查询

bool 查询是最强大、最常用的复合查询,它允许你使用布尔逻辑组合多个查询。

bool 查询的四个子句:

  • must:必须匹配,贡献相关性评分(类似 AND)

  • should:应该匹配,贡献相关性评分(类似 OR)

  • must_not:必须不匹配,不贡献评分(类似 NOT)

  • filter:必须匹配,但不贡献相关性评分,性能更好

json
// 复杂搜索示例:搜索电子产品中价格在2000-5000元之间的手机,优先显示有库存的 GET /products/_search { "query": { "bool": { "must": [ { "match": { "category": "electronics" } }, { "bool": { "should": [ { "match": { "name": "手机" } }, { "match": { "description": "手机" } } ] } } ], "filter": [ { "range": { "price": { "gte": 2000, "lte": 5000 } } } ], "should": [ { "term": { "in_stock": true } } ], "must_not": [ { "term": { "brand": "Unknown" } } ], "minimum_should_match": 1 // 至少满足一个should条件 } } }

filter 与 must 的区别

理解这个区别对性能优化至关重要:

json
// 使用 filter - 不计算评分,性能更好 { "bool": { "filter": [ { "range": { "price": { "gte": 1000 } } }, { "term": { "status": "active" } } ] } } // 使用 must - 计算评分,性能稍差 { "bool": { "must": [ { "range": { "price": { "gte": 1000 } } }, { "term": { "status": "active" } } ] } }

最佳实践:对于不需要相关性评分的精确匹配条件(如范围、状态、标签等),优先使用 filter。

constant_score 查询 - 恒定评分查询

将查询包装起来,为所有匹配的文档赋予相同的恒定分数。

json
// 所有匹配的文档都获得分数 1.0 GET /products/_search { "query": { "constant_score": { "filter": { "term": { "category": "electronics" } }, "boost": 1.0 } } }

这种查询在只需要过滤而不需要复杂评分时性能很好。

实战案例:电商商品搜索

让我们结合所学知识,构建一个完整的电商商品搜索:

创建索引

json
PUT /products { "mappings": { "properties": { "product_id": { "type": "keyword" }, "name": { "type": "text" }, "category": { "type": "keyword" }, "brand": { "type": "keyword" }, "color": { "type": "keyword" }, "memory": { "type": "keyword" }, "size": { "type": "keyword" }, "price": { "type": "float" }, "in_stock": { "type": "boolean" }, "created_at": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||epoch_millis" } } } }

初始化数据

json
POST /products/_bulk { "index": { "_index": "products"} } { "product_id": "P001", "name": "苹果 iPhone 15 Pro Max 银色 256GB", "category": "智能手机", "brand": "苹果", "color": "银色", "memory": "256GB", "size": "6.7英寸", "price": 9999, "in_stock": true, "created_at": "2025-11-01 10:00:00" } { "index": { "_index": "products"} } { "product_id": "P002", "name": "三星 Galaxy S23 Ultra 蓝色 512GB", "category": "智能手机", "brand": "三星", "color": "蓝色", "memory": "512GB", "size": "6.8英寸", "price": 8999, "in_stock": false, "created_at": "2025-11-02 11:00:00" } { "index": { "_index": "products"} } { "product_id": "P003", "name": "小米 Mi 13 Pro 黑色 1TB", "category": "智能手机", "brand": "小米", "color": "黑色", "memory": "1TB", "size": "6.78英寸", "price": 4999, "in_stock": true, "created_at": "2025-11-03 12:00:00" } { "index": { "_index": "products"} } { "product_id": "P004", "name": "华为 Mate 60 Pro 白色 256GB", "category": "智能手机", "brand": "华为", "color": "白色", "memory": "256GB", "size": "6.74英寸", "price": 6999, "in_stock": true, "created_at": "2025-11-04 13:00:00" } { "index": { "_index": "products"} } { "product_id": "P005", "name": "OPPO Find X6 Pro 紫色 512GB", "category": "智能手机", "brand": "OPPO", "color": "紫色", "memory": "512GB", "size": "6.82英寸", "price": 5999, "in_stock": true, "created_at": "2025-11-05 14:00:00" } { "index": { "_index": "products"} } { "product_id": "P006", "name": "vivo X90 Pro+ 黑色 1TB", "category": "智能手机", "brand": "vivo", "color": "黑色", "memory": "1TB", "size": "6.78英寸", "price": 4999, "in_stock": true, "created_at": "2025-11-06 15:00:00" } { "index": { "_index": "products"} } { "product_id": "P007", "name": "荣耀 Magic5 Pro 银色 512GB", "category": "智能手机", "brand": "荣耀", "color": "银色", "memory": "512GB", "size": "6.81英寸", "price": 5999, "in_stock": true, "created_at": "2025-11-07 16:00:00" } { "index": { "_index": "products"} } { "product_id": "P008", "name": "一加 Ace Pro 深空灰 256GB", "category": "智能手机", "brand": "一加", "color": "深空灰", "memory": "256GB", "size": "6.7英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-08 17:00:00" } { "index": { "_index": "products"} } { "product_id": "P009", "name": "realme GT Neo 5 SE 绿色 128GB", "category": "智能手机", "brand": "realme", "color": "绿色", "memory": "128GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-09 18:00:00" } { "index": { "_index": "products"} } { "product_id": "P010", "name": "魅族 20 Pro 黑色 512GB", "category": "智能手机", "brand": "魅族", "color": "黑色", "memory": "512GB", "size": "6.8英寸", "price": 4999, "in_stock": true, "created_at": "2025-11-10 19:00:00" } { "index": { "_index": "products"} } { "product_id": "P011", "name": "中兴 Axon 50 Ultra 蓝色 512GB", "category": "智能手机", "brand": "中兴", "color": "蓝色", "memory": "512GB", "size": "6.8英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-11 20:00:00" } { "index": { "_index": "products"} } { "product_id": "P012", "name": "联想 Moto Edge 30 Ultra 黑色 512GB", "category": "智能手机", "brand": "联想", "color": "黑色", "memory": "512GB", "size": "6.8英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-12 21:00:00" } { "index": { "_index": "products"} } { "product_id": "P013", "name": "诺基亚 G21 Plus 黄色 128GB", "category": "智能手机", "brand": "诺基亚", "color": "黄色", "memory": "128GB", "size": "6.55英寸", "price": 1999, "in_stock": true, "created_at": "2025-11-13 22:00:00" } { "index": { "_index": "products"} } { "product_id": "P014", "name": "zte Axon 40 Ultra 黑色 512GB", "category": "智能手机", "brand": "zte", "color": "黑色", "memory": "512GB", "size": "6.8英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-14 23:00:00" } { "index": { "_index": "products"} } { "product_id": "P015", "name": "荣耀 Play 7T 黑色 128GB", "category": "智能手机", "brand": "荣耀", "color": "黑色", "memory": "128GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-15 00:00:00" } { "index": { "_index": "products"} } { "product_id": "P016", "name": "小米 Redmi Note 13 Pro 黑色 256GB", "category": "智能手机", "brand": "小米", "color": "黑色", "memory": "256GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-16 01:00:00" } { "index": { "_index": "products"} } { "product_id": "P017", "name": "三星 Galaxy A54 金色 128GB", "category": "智能手机", "brand": "三星", "color": "金色", "memory": "128GB", "size": "6.4英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-17 02:00:00" } { "index": { "_index": "products"} } { "product_id": "P018", "name": "苹果 iPhone 14 Pro 极夜黑 128GB", "category": "智能手机", "brand": "苹果", "color": "极夜黑", "memory": "128GB", "size": "6.1英寸", "price": 7999, "in_stock": true, "created_at": "2025-11-01 03:00:00" } { "index": { "_index": "products"} } { "product_id": "P019", "name": "华为 P60 Pro 浅蓝 256GB", "category": "智能手机", "brand": "华为", "color": "浅蓝", "memory": "256GB", "size": "6.67英寸", "price": 5999, "in_stock": true, "created_at": "2025-11-02 04:00:00" } { "index": { "_index": "products"} } { "product_id": "P020", "name": "OPPO Reno10 Pro+ 宇宙黑 512GB", "category": "智能手机", "brand": "OPPO", "color": "宇宙黑", "memory": "512GB", "size": "6.8英寸", "price": 4999, "in_stock": true, "created_at": "2025-11-03 05:00:00" } { "index": { "_index": "products"} } { "product_id": "P021", "name": "vivo Y77t 天青色 128GB", "category": "智能手机", "brand": "vivo", "color": "天青色", "memory": "128GB", "size": "6.67英寸", "price": 1999, "in_stock": true, "created_at": "2025-11-04 06:00:00" } { "index": { "_index": "products"} } { "product_id": "P022", "name": "荣耀 V40 Pro 暗影黑 256GB", "category": "智能手机", "brand": "荣耀", "color": "暗影黑", "memory": "256GB", "size": "6.76英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-05 07:00:00" } { "index": { "_index": "products"} } { "product_id": "P023", "name": "一加 Ace 2V 玫瑰金 128GB", "category": "智能手机", "brand": "一加", "color": "玫瑰金", "memory": "128GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-06 08:00:00" } { "index": { "_index": "products"} } { "product_id": "P024", "name": "realme GT Neo 5 黑色 256GB", "category": "智能手机", "brand": "realme", "color": "黑色", "memory": "256GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-07 09:00:00" } { "index": { "_index": "products"} } { "product_id": "P025", "name": "魅族 20 黑色 128GB", "category": "智能手机", "brand": "魅族", "color": "黑色", "memory": "128GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-08 10:00:00" } { "index": { "_index": "products"} } { "product_id": "P026", "name": "中兴 Axon 30 Ultra 紫色 256GB", "category": "智能手机", "brand": "中兴", "color": "紫色", "memory": "256GB", "size": "6.8英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-09 11:00:00" } { "index": { "_index": "products"} } { "product_id": "P027", "name": "联想 Moto G73 Turbo 黑色 128GB", "category": "智能手机", "brand": "联想", "color": "黑色", "memory": "128GB", "size": "6.8英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-10 12:00:00" } { "index": { "_index": "products"} } { "product_id": "P028", "name": "诺基亚 G21 Plus 银色 128GB", "category": "智能手机", "brand": "诺基亚", "color": "银色", "memory": "128GB", "size": "6.55英寸", "price": 1999, "in_stock": true, "created_at": "2025-11-11 13:00:00" } { "index": { "_index": "products"} } { "product_id": "P029", "name": "zte Axon 30 Ultra 蓝色 256GB", "category": "智能手机", "brand": "zte", "color": "蓝色", "memory": "256GB", "size": "6.8英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-12 14:00:00" } { "index": { "_index": "products"} } { "product_id": "P030", "name": "荣耀 Play 7T 黑色 128GB", "category": "智能手机", "brand": "荣耀", "color": "黑色", "memory": "128GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-13 15:00:00" } { "index": { "_index": "products"} } { "product_id": "P031", "name": "小米 Redmi Note 13 Pro 黑色 256GB", "category": "智能手机", "brand": "小米", "color": "黑色", "memory": "256GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-14 16:00:00" } { "index": { "_index": "products"} } { "product_id": "P032", "name": "三星 Galaxy A54 金色 128GB", "category": "智能手机", "brand": "三星", "color": "金色", "memory": "128GB", "size": "6.4英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-15 17:00:00" } { "index": { "_index": "products"} } { "product_id": "P033", "name": "苹果 iPhone 14 Pro 极夜黑 128GB", "category": "智能手机", "brand": "苹果", "color": "极夜黑", "memory": "128GB", "size": "6.1英寸", "price": 7999, "in_stock": true, "created_at": "2025-11-16 18:00:00" } { "index": { "_index": "products"} } { "product_id": "P034", "name": "华为 P60 Pro 浅蓝 256GB", "category": "智能手机", "brand": "华为", "color": "浅蓝", "memory": "256GB", "size": "6.67英寸", "price": 5999, "in_stock": true, "created_at": "2025-11-17 19:00:00" } { "index": { "_index": "products"} } { "product_id": "P035", "name": "OPPO Reno10 Pro+ 宇宙黑 512GB", "category": "智能手机", "brand": "OPPO", "color": "宇宙黑", "memory": "512GB", "size": "6.8英寸", "price": 4999, "in_stock": true, "created_at": "2025-11-01 20:00:00" } { "index": { "_index": "products"} } { "product_id": "P036", "name": "vivo Y77t 天青色 128GB", "category": "智能手机", "brand": "vivo", "color": "天青色", "memory": "128GB", "size": "6.67英寸", "price": 1999, "in_stock": true, "created_at": "2025-11-02 21:00:00" } { "index": { "_index": "products"} } { "product_id": "P037", "name": "荣耀 V40 Pro 暗影黑 256GB", "category": "智能手机", "brand": "荣耀", "color": "暗影黑", "memory": "256GB", "size": "6.76英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-03 22:00:00" } { "index": { "_index": "products"} } { "product_id": "P038", "name": "一加 Ace 2V 玫瑰金 128GB", "category": "智能手机", "brand": "一加", "color": "玫瑰金", "memory": "128GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-04 23:00:00" } { "index": { "_index": "products"} } { "product_id": "P039", "name": "realme GT Neo 5 黑色 256GB", "category": "智能手机", "brand": "realme", "color": "黑色", "memory": "256GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-05 00:00:00" } { "index": { "_index": "products"} } { "product_id": "P040", "name": "魅族 20 黑色 128GB", "category": "智能手机", "brand": "魅族", "color": "黑色", "memory": "128GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-06 01:00:00" } { "index": { "_index": "products"} } { "product_id": "P041", "name": "中兴 Axon 30 Ultra 紫色 256GB", "category": "智能手机", "brand": "中兴", "color": "紫色", "memory": "256GB", "size": "6.8英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-07 02:00:00" } { "index": { "_index": "products"} } { "product_id": "P042", "name": "联想 Moto G73 Turbo 黑色 128GB", "category": "智能手机", "brand": "联想", "color": "黑色", "memory": "128GB", "size": "6.8英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-08 03:00:00" } { "index": { "_index": "products"} } { "product_id": "P043", "name": "诺基亚 G21 Plus 银色 128GB", "category": "智能手机", "brand": "诺基亚", "color": "银色", "memory": "128GB", "size": "6.55英寸", "price": 1999, "in_stock": true, "created_at": "2025-11-09 04:00:00" } { "index": { "_index": "products"} } { "product_id": "P044", "name": "zte Axon 30 Ultra 蓝色 256GB", "category": "智能手机", "brand": "zte", "color": "蓝色", "memory": "256GB", "size": "6.8英寸", "price": 3999, "in_stock": true, "created_at": "2025-11-10 05:00:00" } { "index": { "_index": "products"} } { "product_id": "P045", "name": "荣耀 Play 7T 黑色 128GB", "category": "智能手机", "brand": "荣耀", "color": "黑色", "memory": "128GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-11 06:00:00" } { "index": { "_index": "products"} } { "product_id": "P046", "name": "小米 Redmi Note 13 Pro 黑色 256GB", "category": "智能手机", "brand": "小米", "color": "黑色", "memory": "256GB", "size": "6.7英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-12 07:00:00" } { "index": { "_index": "products"} } { "product_id": "P047", "name": "三星 Galaxy A54 金色 128GB", "category": "智能手机", "brand": "三星", "color": "金色", "memory": "128GB", "size": "6.4英寸", "price": 2999, "in_stock": true, "created_at": "2025-11-13 08:00:00" } { "index": { "_index": "products"} } { "product_id": "P048", "name": "苹果 iPhone 14 Pro 极夜黑 128GB", "category": "智能手机", "brand": "苹果", "color": "极夜黑", "memory": "128GB", "size": "6.1英寸", "price": 7999, "in_stock": true, "created_at": "2025-11-14 09:00:00" } { "index": { "_index": "products"} } { "product_id": "P049", "name": "华为 P60 Pro 浅蓝 256GB", "category": "智能手机", "brand": "华为", "color": "浅蓝", "memory": "256GB", "size": "6.67英寸", "price": 5999, "in_stock": true, "created_at": "2025-11-15 10:00:00" } { "index": { "_index": "products"} } { "product_id": "P050", "name": "OPPO Reno10 Pro+ 宇宙黑 512GB", "category": "智能手机", "brand": "OPPO", "color": "宇宙黑", "memory": "512GB", "size": "6.8英寸", "price": 4999, "in_stock": true, "created_at": "2025-11-16 11:00:00" }

问题一

请编写一个查询,满足以下条件:

  1. 查找价格在3000元到6000元之间的所有手机。
  2. 这些手机的品牌必须是苹果或三星。
  3. 按照price升序排列结果。
  4. 只返回前10条记录。
  5. 返回的结果中只包含product_id, name, 和 price字段。
  6. 请编写相应的Elasticsearch DSL查询。
json
GET /products/_search { "query": { "bool": { "must": [ { "range": { "price": { "gte": 3000, "lte": 6000 } } }, { "terms": { "brand": [ "苹果", "三星" ] } } ] } }, "size": 10, "sort": [ { "price": { "order": "asc" } } ], "_source": [ "product_id", "name", "price" ] }

问题二

  1. 查找库存状态为true的所有手机。
  2. 这些手机的颜色必须是黑色或白色。
  3. 按照created_at时间降序排列结果。
  4. 只返回前5条记录。
  5. 返回的结果中只包含product_id, name, 和 created_at字段。
json
GET /products/_search { "query": { "bool": { "must": [ { "term": { "in_stock": { "value": true } } } ], "filter": [ { "terms": { "color": [ "黑色", "白色" ] } } ] } }, "size": 5, "sort": [ { "created_at": { "order": "desc" } } ], "_source": [ "product_id","name","created_at" ] }

Java 代码示例

作为 Java 开发者,你可能更关心如何在代码中构建这些查询:

java
// 使用 Java High Level REST Client SearchRequest searchRequest = new SearchRequest("products"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 构建 bool 查询 BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() .must(QueryBuilders.multiMatchQuery("无线蓝牙耳机", "name", "description") .operator(Operator.AND)) .filter(QueryBuilders.rangeQuery("price").gte(100).lte(1000)) .filter(QueryBuilders.termsQuery("brand", "Sony", "Bose", "Sennheiser")) .should(QueryBuilders.termQuery("is_featured", true).boost(2)) .mustNot(QueryBuilders.termQuery("status", "discontinued")) .minimumShouldMatch(1); sourceBuilder.query(boolQuery); sourceBuilder.from(0); sourceBuilder.size(20); sourceBuilder.sort("_score", SortOrder.DESC); sourceBuilder.sort("created_at", SortOrder.DESC); searchRequest.source(sourceBuilder); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

总结

通过本文,我们深入学习了:

  • 精准匹配查询:term, terms, range, exists 等,用于精确值查找

  • 全文搜索查询:match, match_phrase, multi_match 等,用于文本内容搜索

  • 复合查询:主要是 bool 查询,用于构建复杂的搜索逻辑

关键要点:

  • 理解字段类型:text 字段适合全文搜索,keyword 字段适合精准匹配

  • 善用 filter 上下文:对于不关心评分的精确匹配,使用 filter 提升性能

  • 合理使用 bool 查询:它是构建复杂搜索需求的瑞士军刀

  • 注意评分影响:must 和 should 影响评分,filter 和 must_not 不影响

思考题:尝试用今天学到的知识,构建一个搜索你业务场景的查询,比如博客文章搜索、用户搜索或日志搜索。

本文作者:柳始恭

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!