第二阶段 17 · multi_match 多字段匹配

阶段:第二阶段 / 查询能力

ES 查询:multi_match | PostgreSQL 对照:多列 OR ILIKE


1. 概念

multi_matchmatch 的多字段版本:一个关键词,同时在多个字段里搜

典型场景:一个搜索框,输入的词要在「描述、料号、客户名」里都找一遍。


2. PostgreSQL 对照

sql 复制代码
SELECT * FROM salesdata
WHERE description ILIKE '%carbon%'
   OR material    ILIKE '%carbon%'
   OR customer_nm ILIKE '%carbon%';

multi_match 把这一串 OR ILIKE 收成一个查询,还自带相关性打分。


3. ES DSL

基本用法

复制代码
GET salesdata_idx/_search
{
  "query": {
    "multi_match": {
      "query": "carbon",
      "fields": ["description", "material", "customer_nm"]
    }
  }
}

字段加权(boost,让某字段更重要)

复制代码
"multi_match": {
  "query": "carbon",
  "fields": ["description^3", "material", "customer_nm"]
}

description^3 表示 description 命中的权重是其他字段的 3 倍。

type 常用取值

type 行为
best_fields(默认) 取匹配最好的单个字段分数
most_fields 累加各字段分数(越多字段命中越高)
cross_fields 把多字段当成一个大字段(适合姓名/地址跨字段)
phrase 各字段按短语匹配
复制代码
"multi_match": {
  "query": "carbon laptop",
  "fields": ["description", "material"],
  "type": "cross_fields",
  "operator": "and"
}

4. Spring Boot 实现

java 复制代码
@Component
public class Doc17MultiMatchQuery {

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    /** 一个关键词,多字段搜索 */
    public List<Map<String, Object>> multiMatch(String indexName, String keyword,
                                                List<String> fields) throws IOException {
        SearchResponse<Map> resp = elasticsearchClient.search(s -> s
                .index(indexName)
                .query(q -> q.multiMatch(mm -> mm
                        .query(keyword)
                        .fields(fields))),
                Map.class);
        return toSourceList(resp);
    }

    /** 带字段加权与 type */
    public List<Map<String, Object>> multiMatchBoosted(String indexName, String keyword)
            throws IOException {
        SearchResponse<Map> resp = elasticsearchClient.search(s -> s
                .index(indexName)
                .query(q -> q.multiMatch(mm -> mm
                        .query(keyword)
                        .fields("description^3", "material", "customer_nm")
                        .type(TextQueryType.BestFields))),
                Map.class);
        return toSourceList(resp);
    }

    private List<Map<String, Object>> toSourceList(SearchResponse<Map> resp) {
        return resp.hits().hits().stream()
                .map(Hit::source).filter(Objects::nonNull)
                .collect(Collectors.toList());
    }
}

import:co.elastic.clients.elasticsearch._types.query_dsl.TextQueryType

返回强类型 Java 对象(推荐,替代裸 Map)

Map.class 换成 DTO 的 Class(第 11 篇定义的 OrderDoc,用 @JsonProperty 映射下划线字段),

即可直接拿到强类型列表:

java 复制代码
/** 一个关键词多字段搜索,返回 List<OrderDoc> */
public List<OrderDoc> multiMatchTyped(String indexName, String keyword, List<String> fields)
        throws IOException {
    SearchResponse<OrderDoc> resp = elasticsearchClient.search(s -> s
            .index(indexName)
            .query(q -> q.multiMatch(mm -> mm.query(keyword).fields(fields))),
            OrderDoc.class);             // ← 关键:DTO 的 Class,而非 Map.class

    return resp.hits().hits().stream()
            .map(Hit::source).filter(Objects::nonNull)
            .collect(Collectors.toList());
}

全文打分场景更常用 Map_score/高亮;确定返回结构后,对外接口建议用 DTO。


5. 坑与最佳实践

  1. 字段类型要一致适配 :全文搜索的字段应是 text;对 keyword 用 multi_match 效果有限。
  2. 选对 type :找「哪个字段最匹配」用 best_fields;姓名/地址这种跨字段用 cross_fields
  3. 合理加权 :核心字段 ^ 加权提升排序质量,别所有字段都加。
  4. 搜索框场景常配 operator=andminimum_should_match,避免结果太宽泛。

下一篇

18-sort-分页.md

相关推荐
倒流时光三十年5 小时前
第三阶段 23 · 嵌套与子聚合 / top_hits
es
倒流时光三十年5 小时前
第二阶段 19 · _source 字段裁剪
es
倒流时光三十年2 天前
第二阶段 15 · prefix / wildcard / fuzzy 模糊匹配
es
粗体鱼2 天前
RAG/Agent 记忆混合检索多路召回:RRF 算法与Chunk RRF、Document RRF如何决策TopK
postgresql·milvus·es·rag·rff·mermory
huisheng_qaq2 个月前
【项目篇-01】Vmware虚拟机和环境安装配置
redis·mysql·canal·rocketmq·es·vaware虚拟机
JAVA面经实录9172 个月前
Elasticsearch 完整版完整知识体系
java·elasticsearch·搜索引擎·es
代码讲故事2 个月前
在没有kibana的ES(elasticsearch)线上生产环境集群中,如何通过命令行修改或增加字段而不需要reindex?
大数据·elasticsearch·搜索引擎·命令行·es·索引·模版
yurenpai(27届找实习中)2 个月前
Elasticsearch 核心总结 + 面试题实战(黑马点评项目)
redis·es
徐小青青啊2 个月前
es集群不中断实时数据更新损坏节点硬盘
大数据·elasticsearch·搜索引擎·es