<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Lucene on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/lucene/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 20 Jun 2020 09:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/lucene/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>《Elasticsearch 权威指南》详解：零基础读懂 ES 的核心知识体系</title>
      <link>https://ftmao.com/blog/bookstore/elasticsearch-definitive-guide-notes/</link>
      <pubDate>Sat, 20 Jun 2020 09:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/bookstore/elasticsearch-definitive-guide-notes/</guid>
      <description>&lt;h1 id=&#34;elasticsearch-权威指南详解零基础读懂-es-的核心知识体系&#34;&gt;《Elasticsearch 权威指南》详解：零基础读懂 ES 的核心知识体系&lt;/h1&gt;
&lt;p&gt;《Elasticsearch 权威指南》（Elasticsearch: The Definitive Guide，Clinton Gormley &amp;amp; Zachary Tong 著）是学习 Elasticsearch 公认的第一本书。中文版由 looly 等人组织社区翻译。它不是 API 手册，而是沿着&amp;quot;&lt;strong&gt;为什么这样设计&lt;/strong&gt;&amp;ldquo;的路线，把 ES 从安装、文档 CRUD 一路讲到分布式内核、分词、相关性算分和集群运维。&lt;/p&gt;
&lt;p&gt;这本书基于 ES 1.x/2.x 时代写成，个别细节（如 type 概念、TF/IDF 默认评分）在新版本有变化，但&lt;strong&gt;核心思想至今不变&lt;/strong&gt;。本文面向从未读过这本书的人，按&amp;quot;基础概念 → 分布式原理 → 搜索 → 语言处理 → 聚合 → 建模 → 运维&amp;quot;的顺序完整梳理，配图解和可直接运行的实例。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一elasticsearch-是什么先建立直觉&#34;&gt;一、Elasticsearch 是什么：先建立直觉&lt;/h2&gt;
&lt;p&gt;书的开篇用一句话定义 ES：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Elasticsearch 是一个&lt;strong&gt;分布式的、实时的文档存储与搜索引擎&lt;/strong&gt;，基于 Apache Lucene 构建，通过 RESTful API 暴露 Lucene 的全部威力。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lucene 本身是一个 Java 搜索库，强大但难用——ES 的价值在于把 Lucene 包装成一个可以水平扩展、开箱即用的分布式系统。书中列举的典型用户包括 Wikipedia（全文搜索 + 高亮 + 输入即搜 + 拼写纠错）、GitHub（检索 1300 亿行代码）、StackOverflow（&amp;ldquo;你可能想问&amp;quot;的 more-like-this 推荐）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;与关系型数据库的概念对照&lt;/strong&gt;（这是全书最重要的入门表格）：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;关系型数据库&lt;/th&gt;
					&lt;th&gt;Elasticsearch&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Database（库）&lt;/td&gt;
					&lt;td&gt;Index（索引）&lt;/td&gt;
					&lt;td&gt;逻辑命名空间&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Table（表）&lt;/td&gt;
					&lt;td&gt;Type（类型）&lt;/td&gt;
					&lt;td&gt;⚠️ 新版已废弃，理解旧书时需要&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Row（行）&lt;/td&gt;
					&lt;td&gt;Document（文档）&lt;/td&gt;
					&lt;td&gt;一条 JSON 记录&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Column（列）&lt;/td&gt;
					&lt;td&gt;Field（字段）&lt;/td&gt;
					&lt;td&gt;文档的属性&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Schema（表结构）&lt;/td&gt;
					&lt;td&gt;Mapping（映射）&lt;/td&gt;
					&lt;td&gt;字段类型定义&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SQL&lt;/td&gt;
					&lt;td&gt;Query DSL&lt;/td&gt;
					&lt;td&gt;查询语言&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;index（索引，动词）&lt;/td&gt;
					&lt;td&gt;index（索引，动词）&lt;/td&gt;
					&lt;td&gt;把文档写入&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;关键区别&lt;/strong&gt;：数据库假设&amp;quot;每行结构相同&amp;rdquo;，ES 的文档是无模式的 JSON（虽然实际上有 mapping 约束）；数据库为&amp;quot;精确存取&amp;quot;优化，ES 为&amp;rdquo;&lt;strong&gt;相关性检索&lt;/strong&gt;&amp;ldquo;优化——它回答的问题不是&amp;quot;有没有&amp;rdquo;，而是&amp;quot;&lt;strong&gt;有多相关&lt;/strong&gt;&amp;quot;。&lt;/p&gt;
&lt;h3 id=&#34;11-十分钟跑起来书中的第一个例子&#34;&gt;1.1 十分钟跑起来：书中的第一个例子&lt;/h3&gt;
&lt;p&gt;全书第一章用一家虚构公司 megacorp 的员工数据贯穿：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 写入一个员工文档（PUT = 指定 ID 创建/覆盖）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PUT /megacorp/employee/1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;first_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;John&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;last_name&amp;#34;&lt;/span&gt;:  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Smith&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;age&amp;#34;&lt;/span&gt;:        25,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;about&amp;#34;&lt;/span&gt;:      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;I love to go rock climbing&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;interests&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;sports&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;music&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 取回（GET）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /megacorp/employee/1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 轻量搜索：查询字符串&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /megacorp/employee/_search?q&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;last_name:Smith
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 正式搜索：Query DSL（JSON 请求体）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /megacorp/employee/_search
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;match&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;last_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Smith&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;注意这里&lt;strong&gt;没有建库、没有建表、没有定义字段类型&lt;/strong&gt;——这就是&amp;quot;无模式&amp;quot;体验。但书里马上提醒：无模式是假象，ES 在背后做了&lt;strong&gt;动态映射（dynamic mapping）&lt;/strong&gt;，第一次见 &lt;code&gt;&amp;quot;age&amp;quot;: 25&lt;/code&gt; 就推断 age 是 long。生产环境应该显式定义 mapping（第四章详解）。&lt;/p&gt;
&lt;h3 id=&#34;12-一个展示相关性的例子&#34;&gt;1.2 一个展示&amp;quot;相关性&amp;quot;的例子&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /megacorp/employee/_search
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bool&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;must&amp;#34;&lt;/span&gt;:     &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;match&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;about&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rock climbing&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;filter&amp;#34;&lt;/span&gt;:   &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;range&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;age&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gt&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;返回结果中每个文档带一个 &lt;code&gt;_score&lt;/code&gt;（相关性得分），按得分降序排列。&lt;code&gt;must&lt;/code&gt; 里的 match 参与算分，&lt;code&gt;filter&lt;/code&gt; 里的 range 只过滤不算分——&lt;strong&gt;这是全书反复出现的 query/filter 二分法&lt;/strong&gt;，第六章详解。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二分布式内核es-为什么能水平扩展&#34;&gt;二、分布式内核：ES 为什么能水平扩展&lt;/h2&gt;
&lt;p&gt;这是全书的硬核部分，也是 ES 区别于&amp;quot;单机 Lucene&amp;quot;的根本。&lt;/p&gt;
&lt;h3 id=&#34;21-集群节点与分片&#34;&gt;2.1 集群、节点与分片&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    subgraph CLUSTER[&amp;#34;集群 cluster（一个 cluster.name）&amp;#34;]
        N1[&amp;#34;节点 Node 1&amp;lt;br/&amp;gt;（一个 ES 进程）&amp;#34;]
        N2[&amp;#34;节点 Node 2&amp;#34;]
        N3[&amp;#34;节点 Node 3&amp;#34;]
    end
    subgraph IDX[&amp;#34;索引 blogs（3 主分片 × 1 副本）&amp;#34;]
        P0[&amp;#34;主分片 P0&amp;#34;] --- R0[&amp;#34;副本分片 R0&amp;#34;]
        P1[&amp;#34;主分片 P1&amp;#34;] --- R1[&amp;#34;副本分片 R1&amp;#34;]
        P2[&amp;#34;主分片 P2&amp;#34;] --- R2[&amp;#34;副本分片 R2&amp;#34;]
    end
    N1 -.承载.- P0
    N1 -.承载.- R1
    N2 -.承载.- P1
    N2 -.承载.- R2
    N3 -.承载.- P2
    N3 -.承载.- R0
    style CLUSTER fill:#e8f0fe&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;要点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;分片（shard）是 ES 分布式能力的最小单元&lt;/strong&gt;：一个分片就是一个完整的 Lucene 实例。索引只是&amp;quot;一组分片的逻辑命名空间&amp;quot;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主分片数在创建索引时定死&lt;/strong&gt;（路由哈希依赖它），副本分片数可以随时调整。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主副本不允许在同一节点&lt;/strong&gt;——这样任意一台机器宕机，数据不丢、搜索不中断。&lt;/li&gt;
&lt;li&gt;集群健康三态：&lt;code&gt;green&lt;/code&gt;（所有主副本都就位）/ &lt;code&gt;yellow&lt;/code&gt;（主分片齐了，副本缺）/ &lt;code&gt;red&lt;/code&gt;（有主分片丢失，数据不可用）。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /_cluster/health   &lt;span style=&#34;color:#75715e&#34;&gt;# 全书最常用的运维命令&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;22-扩容为什么是免费的&#34;&gt;2.2 扩容为什么是&amp;quot;免费&amp;quot;的&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    subgraph 三节点[&amp;#34;3 节点&amp;#34;]
        A1[&amp;#34;P0 R1&amp;#34;] 
        B1[&amp;#34;P1 R2&amp;#34;]
        C1[&amp;#34;P2 R0&amp;#34;]
    end
    subgraph 加一节点[&amp;#34;加入第 4 节点后：自动再平衡&amp;#34;]
        A2[&amp;#34;P0&amp;#34;]
        B2[&amp;#34;P1 R0&amp;#34;]
        C2[&amp;#34;P2&amp;#34;]
        D2[&amp;#34;R1 R2&amp;#34;]
    end
    三节点 --&amp;gt;|&amp;#34;分片自动迁移&amp;lt;br/&amp;gt;无需停机&amp;#34;| 加一节点&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;分片是 Lucene 实例，搬分片 = 搬一个独立的小搜索引擎。ES 自动把分片挪到新节点，流量自动均摊。&lt;strong&gt;垂直扩容（换大机器）之外，ES 天生支持水平扩容（加机器）&lt;/strong&gt;——这是书里&amp;quot;scale up vs scale out&amp;quot;一节的核心论点。&lt;/p&gt;
&lt;h3 id=&#34;23-文档是怎么找到家的路由&#34;&gt;2.3 文档是怎么找到家的：路由&lt;/h3&gt;
&lt;p&gt;写入/读取一个文档时，ES 用它定位分片：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;shard = hash(routing) % number_of_primary_shards&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;code&gt;routing&lt;/code&gt; 默认是文档的 &lt;code&gt;_id&lt;/code&gt;，也可以自定义（比如按用户 ID 路由，让同一用户的数据落在同一分片）。&lt;strong&gt;这解释了主分片数为什么不能改&lt;/strong&gt;：改了模数，所有已有文档的哈希结果全部失效。&lt;/p&gt;
&lt;h3 id=&#34;24-写入与读取的分布式流程&#34;&gt;2.4 写入与读取的分布式流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant C as 客户端
    participant N as 协调节点&amp;lt;br/&amp;gt;（收到请求的任意节点）
    participant P as 主分片所在节点
    participant R1 as 副本节点1
    participant R2 as 副本节点2

    Note over C,N: 写入流程
    C-&amp;gt;&amp;gt;N: PUT /blogs/post/123
    N-&amp;gt;&amp;gt;N: 计算路由 hash(_id)%3 → P1
    N-&amp;gt;&amp;gt;P: 转发写入
    P-&amp;gt;&amp;gt;P: 本地写 Lucene + translog
    par 并行同步副本
        P-&amp;gt;&amp;gt;R1: 复制写入
        P-&amp;gt;&amp;gt;R2: 复制写入
    end
    R1--&amp;gt;&amp;gt;P: ack
    R2--&amp;gt;&amp;gt;P: ack
    P--&amp;gt;&amp;gt;N: 成功
    N--&amp;gt;&amp;gt;C: 201 + _version

    Note over C,N: 读取流程
    C-&amp;gt;&amp;gt;N: GET /blogs/post/123
    N-&amp;gt;&amp;gt;N: 路由计算 → 分片 P1
    N-&amp;gt;&amp;gt;R2: 主/副本轮询负载均衡
    R2--&amp;gt;&amp;gt;N: 文档
    N--&amp;gt;&amp;gt;C: 200 + _source&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;两个关键设计：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;任何节点都能当协调节点&lt;/strong&gt;——没有单点入口；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;写走主分片，读可以走主或副本&lt;/strong&gt;——副本不仅容灾，还分摊读流量。加副本 = 加读吞吐。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三近实时的秘密refreshtranslog-与段合并&#34;&gt;三、近实时的秘密：refresh、translog 与段合并&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;文档写入后为什么默认 1 秒才能搜到？&amp;ldquo;回答这个问题需要理解 Lucene 的存储模型。&lt;/p&gt;
&lt;h3 id=&#34;31-倒排索引与不可变段&#34;&gt;3.1 倒排索引与不可变段&lt;/h3&gt;
&lt;p&gt;ES 快的根源是&lt;strong&gt;倒排索引&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    subgraph 词典[&amp;#34;Term Dictionary&amp;#34;]
        T1[&amp;#34;climbing&amp;#34;]
        T2[&amp;#34;music&amp;#34;]
        T3[&amp;#34;rock&amp;#34;]
    end
    subgraph 倒排表[&amp;#34;Posting List&amp;#34;]
        L1[&amp;#34;doc 1, doc 5&amp;#34;]
        L2[&amp;#34;doc 1, doc 3&amp;#34;]
        L3[&amp;#34;doc 1&amp;#34;]
    end
    T1 --&amp;gt; L1
    T2 --&amp;gt; L2
    T3 --&amp;gt; L3&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;Lucene 把倒排索引持久化为&lt;strong&gt;段（segment）&lt;/strong&gt;，段一旦写出就&lt;strong&gt;不可变（immutable）&lt;/strong&gt;。不可变性带来一串好处：不需要锁、可以进文件系统缓存、删除只需打标记。代价是：&lt;strong&gt;更新 = 删旧 + 建新&lt;/strong&gt;，新写的文档必须先攒成新段才能被搜索。&lt;/p&gt;
&lt;h3 id=&#34;32-完整链路&#34;&gt;3.2 完整链路&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    W[&amp;#34;文档写入请求&amp;#34;] --&amp;gt; MEM[&amp;#34;内存缓冲区&amp;#34;]
    W --&amp;gt; TL[&amp;#34;translog&amp;lt;br/&amp;gt;（先写 WAL，防宕机丢数据）&amp;#34;]
    MEM --&amp;gt;|&amp;#34;refresh&amp;lt;br/&amp;gt;默认每 1 秒&amp;#34;| SEG[&amp;#34;新 segment&amp;lt;br/&amp;gt;写入文件系统缓存&amp;lt;br/&amp;gt;→ 立即可被搜索&amp;#34;]
    SEG --&amp;gt;|&amp;#34;flush&amp;lt;br/&amp;gt;translog 满或定时&amp;#34;| DISK[&amp;#34;fsync 落盘&amp;lt;br/&amp;gt;清空 translog&amp;#34;]
    SEG -.-&amp;gt;|&amp;#34;后台 merge&amp;#34;| BIG[&amp;#34;小段合并成大段&amp;lt;br/&amp;gt;物理清除已删文档&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三个动作的分工：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;refresh&lt;/strong&gt;：内存 → 新的可搜索 segment（在文件系统缓存里，不落盘）。这就是&amp;quot;近实时（NRT）&amp;ldquo;的来源——默认 1 秒延迟。批量导入时可以调大 &lt;code&gt;refresh_interval&lt;/code&gt; 换吞吐。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;translog&lt;/strong&gt;：预写日志。每个写入先记 translog，节点宕机后用它重放还没 flush 的数据。这是&amp;quot;ES 不丢数据&amp;quot;的底气。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;flush&lt;/strong&gt;：真正 fsync 落盘 + 清空 translog。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;merge&lt;/strong&gt;：小段太多会拖慢搜索（每个查询都要遍历所有段），后台线程持续把小段合并成大段，并顺带物理删除被标记删除的文档。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;给初学者的记忆法&lt;/strong&gt;：refresh 管&amp;quot;搜得到&amp;rdquo;，flush 管&amp;quot;丢不了&amp;rdquo;，merge 管&amp;quot;搜得快&amp;rdquo;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四映射与分析数据进-es-之前发生了什么&#34;&gt;四、映射与分析：数据进 ES 之前发生了什么&lt;/h2&gt;
&lt;h3 id=&#34;41-mapping字段的类型决定它能怎么被查&#34;&gt;4.1 Mapping：字段的类型决定它能怎么被查&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;PUT&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;/blogs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;mappings&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;properties&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;:    { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;analyzer&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ik_max_word&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;:   { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;keyword&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;views&amp;#34;&lt;/span&gt;:    { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;integer&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;created&amp;#34;&lt;/span&gt;:  { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;date&amp;#34;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;最核心的类型二分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;text&lt;/code&gt;&lt;/strong&gt;：全文字段，会被&lt;strong&gt;分词&lt;/strong&gt;后存入倒排索引，用于 &lt;code&gt;match&lt;/code&gt; 全文检索；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;keyword&lt;/code&gt;&lt;/strong&gt;：精确值字段，&lt;strong&gt;原样&lt;/strong&gt;入索引，用于过滤、排序、聚合。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;书中金句：&amp;quot;&lt;strong&gt;exact value 和 full text 的区别，是 SQL 世界和搜索世界的分界&lt;/strong&gt;&amp;quot;。用 keyword 字段做 match 全文搜索（或反过来）是新手最常见的错误。&lt;/p&gt;
&lt;p&gt;⚠️ 版本提示：原书写作时还是 &lt;code&gt;string&lt;/code&gt; + &lt;code&gt;analyzed/not_analyzed&lt;/code&gt; 的写法，ES 5.x 起拆分为 &lt;code&gt;text&lt;/code&gt;/&lt;code&gt;keyword&lt;/code&gt;，思想完全一致。&lt;/p&gt;
&lt;h3 id=&#34;42-分析链分词是怎么发生的&#34;&gt;4.2 分析链：分词是怎么发生的&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[&amp;#34;原始文本&amp;lt;br/&amp;gt;&amp;#39;The Quick Brown Fox!&amp;#39;&amp;#34;] --&amp;gt; CF[&amp;#34;Character Filter&amp;lt;br/&amp;gt;字符过滤&amp;lt;br/&amp;gt;（去 HTML、字符映射）&amp;#34;]
    CF --&amp;gt; TK[&amp;#34;Tokenizer&amp;lt;br/&amp;gt;分词器&amp;lt;br/&amp;gt;&amp;#39;The&amp;#39;,&amp;#39;Quick&amp;#39;,&amp;#39;Brown&amp;#39;,&amp;#39;Fox&amp;#39;&amp;#34;]
    TK --&amp;gt; TF[&amp;#34;Token Filter&amp;lt;br/&amp;gt;词项过滤器&amp;lt;br/&amp;gt;lowercase → 停用词 → 词干提取&amp;#34;]
    TF --&amp;gt; R[&amp;#34;最终词项&amp;lt;br/&amp;gt;&amp;#39;quick&amp;#39;,&amp;#39;brown&amp;#39;,&amp;#39;fox&amp;#39;&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Character Filter&lt;/strong&gt;：分词前做字符级预处理；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tokenizer&lt;/strong&gt;：把文本切成词项（一个分析器&lt;strong&gt;只能有一个&lt;/strong&gt; tokenizer）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Token Filter&lt;/strong&gt;：对词项再加工，可串联多个（lowercase、停用词、同义词、词干提取）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;内置的 &lt;code&gt;standard&lt;/code&gt; 分析器 = standard tokenizer + lowercase + stop。可以用 &lt;code&gt;_analyze&lt;/code&gt; API 眼见为实：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;POST /_analyze
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;analyzer&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;standard&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;The Quick Brown Fox!&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# → the, quick, brown, fox（&amp;#39;The&amp;#39; 被小写化）&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;中文场景&lt;/strong&gt;：标准分词器会把中文逐字切开，效果很差。社区方案是 IK 分词器（&lt;code&gt;ik_max_word&lt;/code&gt; 细粒度建索引、&lt;code&gt;ik_smart&lt;/code&gt; 粗粒度搜索），这是中文 ES 项目的标配。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;索引时与搜索时的分析必须配套&lt;/strong&gt;：文档里的 &lt;code&gt;&amp;quot;Fox&amp;quot;&lt;/code&gt; 入库时被分析成 &lt;code&gt;fox&lt;/code&gt;；搜索 &lt;code&gt;&amp;quot;FOX&amp;quot;&lt;/code&gt; 时查询词也会被同一个分析器处理成 &lt;code&gt;fox&lt;/code&gt; 去匹配——&lt;strong&gt;这就是为什么 ES 搜索&amp;quot;不区分大小写&amp;quot;&lt;/strong&gt;：不是查询忽略了大小写，而是两边都被 lowercased 了。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五搜索query-dsl-的全景&#34;&gt;五、搜索：Query DSL 的全景&lt;/h2&gt;
&lt;h3 id=&#34;51-query-与-filter全书最重要的性能概念&#34;&gt;5.1 Query 与 Filter：全书最重要的性能概念&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    Q[&amp;#34;Query 上下文&amp;lt;br/&amp;gt;&amp;#39;这个文档和查询有多相关？&amp;#39;&amp;#34;]
    F[&amp;#34;Filter 上下文&amp;lt;br/&amp;gt;&amp;#39;这个文档是否匹配？&amp;#39;&amp;#34;]
    Q --&amp;gt; A1[&amp;#34;计算 _score&amp;lt;br/&amp;gt;结果按相关性排序&amp;#34;]
    F --&amp;gt; A2[&amp;#34;只答 yes/no&amp;lt;br/&amp;gt;不算分、结果可被缓存&amp;#34;]
    style Q fill:#fef3e8
    style F fill:#e1f5e1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;经验法则：能用 filter 就不用 query&lt;/strong&gt;。过滤条件（状态、时间范围、ID 列表）放 filter，既省算分开销又能命中 bitset 缓存。&lt;/p&gt;
&lt;h3 id=&#34;52-常用查询速查&#34;&gt;5.2 常用查询速查&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;查询&lt;/th&gt;
					&lt;th&gt;用途&lt;/th&gt;
					&lt;th&gt;例子&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;match&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;全文搜索（会分词）&lt;/td&gt;
					&lt;td&gt;标题含&amp;quot;登山 装备&amp;quot;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;term&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;精确匹配（不分词）&lt;/td&gt;
					&lt;td&gt;status 等于 &amp;ldquo;published&amp;rdquo;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;terms&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;多值精确匹配&lt;/td&gt;
					&lt;td&gt;标签 in [&amp;ldquo;科幻&amp;rdquo;,&amp;ldquo;动作&amp;rdquo;]&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;range&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;范围&lt;/td&gt;
					&lt;td&gt;age ≥ 30&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;exists&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;字段非空&lt;/td&gt;
					&lt;td&gt;必须有 poster 字段&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;multi_match&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;跨多字段全文&lt;/td&gt;
					&lt;td&gt;同时在标题和简介里搜&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;match_phrase&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;短语匹配（词序相邻）&lt;/td&gt;
					&lt;td&gt;搜 &amp;ldquo;rock climbing&amp;rdquo; 不拆词&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;组合一切&lt;/td&gt;
					&lt;td&gt;见下&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;53-bool-查询乐高积木&#34;&gt;5.3 bool 查询：乐高积木&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;GET&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;/megacorp/employee/_search&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;bool&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;must&amp;#34;&lt;/span&gt;:     [ { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;match&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;about&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;rock climbing&amp;#34;&lt;/span&gt; } } ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;should&amp;#34;&lt;/span&gt;:   [ { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;match&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;interests&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;music&amp;#34;&lt;/span&gt; } } ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;must_not&amp;#34;&lt;/span&gt;: [ { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;term&amp;#34;&lt;/span&gt;:  { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;last_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;smith&amp;#34;&lt;/span&gt; } } ],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;filter&amp;#34;&lt;/span&gt;:   [ { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;range&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;age&amp;#34;&lt;/span&gt;: { &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;gte&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt; } } } ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;must&lt;/code&gt;：必须匹配，参与算分；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;should&lt;/code&gt;：最好匹配，匹配上加分（没有 must/filter 时至少命中一个）；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;must_not&lt;/code&gt;：必须不匹配，不参与算分（在 filter 上下文执行）；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;filter&lt;/code&gt;：必须匹配，不参与算分。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;所有复杂查询都是这四块积木的嵌套&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;54-相关性算分_score-是怎么来的&#34;&gt;5.4 相关性算分：_score 是怎么来的&lt;/h3&gt;
&lt;p&gt;书里讲了经典的 &lt;strong&gt;TF/IDF&lt;/strong&gt; 模型（新版本默认换成 BM25，思想相同，多了文档长度归一化）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;词频 TF&lt;/strong&gt;：词在本文档出现越多，越相关；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;逆文档频率 IDF&lt;/strong&gt;：词在所有文档中越罕见，区分度越高（&amp;ldquo;的&amp;quot;不值钱，&amp;ldquo;攀岩&amp;quot;值钱）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;字段长度&lt;/strong&gt;：字段越短，匹配越&amp;quot;精悍&amp;rdquo;，得分越高。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对结果有疑问时用 &lt;code&gt;_explain&lt;/code&gt; API 看算分过程——这是调搜索体验的第一件工具。&lt;/p&gt;
&lt;h3 id=&#34;55-深分页陷阱&#34;&gt;5.5 深分页陷阱&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /_search?from&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;10000&amp;amp;size&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;# ⚠️ 危险&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;分布式搜索是 &lt;strong&gt;scatter-gather&lt;/strong&gt; 模式：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant C as 客户端
    participant CO as 协调节点
    participant S0 as 分片0
    participant S1 as 分片1
    participant S2 as 分片2
    C-&amp;gt;&amp;gt;CO: from=10000, size=10
    par scatter
        CO-&amp;gt;&amp;gt;S0: 各分片先取 Top 10010
        CO-&amp;gt;&amp;gt;S1: 各分片先取 Top 10010
        CO-&amp;gt;&amp;gt;S2: 各分片先取 Top 10010
    end
    S0--&amp;gt;&amp;gt;CO: 10010 条
    S1--&amp;gt;&amp;gt;CO: 10010 条
    S2--&amp;gt;&amp;gt;CO: 10010 条
    CO-&amp;gt;&amp;gt;CO: 归并 30030 条，取 10001~10010
    CO--&amp;gt;&amp;gt;C: 10 条&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;取第 1001 页，要在每个分片各取 10010 条再归并。&lt;strong&gt;深度翻页成本线性爆炸&lt;/strong&gt;，书里的忠告是&amp;quot;不要在搜索场景做深翻页&amp;rdquo;；确实需要遍历全量时，用 &lt;code&gt;scroll&lt;/code&gt;（游标快照）或新版本的 &lt;code&gt;search_after&lt;/code&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六处理人类语言&#34;&gt;六、处理人类语言&lt;/h2&gt;
&lt;p&gt;这一部分是本书区别于普通教程的精华：搜索的本质对手是&lt;strong&gt;自然语言的模糊性&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;语言分析器&lt;/strong&gt;：英语词干提取（&lt;code&gt;foxes&lt;/code&gt;→&lt;code&gt;fox&lt;/code&gt;）、德语的复合词拆分、中文/日文的无空格分词。每种语言的正确处理方式完全不同——&lt;strong&gt;选对语言分析器比调任何参数都重要&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;拼写纠错（did-you-mean）&lt;/strong&gt;：&lt;code&gt;term suggester&lt;/code&gt; / &lt;code&gt;phrase suggester&lt;/code&gt;，&amp;ldquo;你搜的是不是 elasticsearch？&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输入即搜（search-as-you-type）&lt;/strong&gt;：用 &lt;code&gt;edge ngram&lt;/code&gt;（前缀 ngram）在索引时把 &lt;code&gt;&amp;quot;elasticsearch&amp;quot;&lt;/code&gt; 切成 &lt;code&gt;e, el, ela, ...&lt;/code&gt;，用户每敲一个字母就能命中。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;近似匹配&lt;/strong&gt;：&lt;code&gt;match&lt;/code&gt; 的 &lt;code&gt;fuzziness&lt;/code&gt; 参数基于编辑距离，容忍拼写错误（&lt;code&gt;searching&lt;/code&gt; 打成 &lt;code&gt;serching&lt;/code&gt; 也能命中）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;近似短语&lt;/strong&gt;：&lt;code&gt;match_phrase&lt;/code&gt; 的 &lt;code&gt;slop&lt;/code&gt; 参数允许词与词之间隔着几个词仍算匹配。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这一部分的共同心法：&lt;strong&gt;召回率与准确率的权衡&lt;/strong&gt;。ngram 开得越大、fuzziness 越高，召回越好但噪音越多；工程上常用&amp;quot;多层子字段&amp;quot;（精确字段 + 分词字段 + ngram 字段）分层兜底。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七聚合从搜索到分析&#34;&gt;七、聚合：从搜索到分析&lt;/h2&gt;
&lt;p&gt;搜索回答&amp;quot;哪些文档匹配&amp;quot;，&lt;strong&gt;聚合（aggregations）&lt;/strong&gt; 回答&amp;quot;数据整体长什么样&amp;quot;。聚合分两大类，可以无限嵌套：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;桶（Bucket）聚合&lt;/strong&gt;：把文档分组——&lt;code&gt;terms&lt;/code&gt;（按字段值）、&lt;code&gt;date_histogram&lt;/code&gt;（按时间）、&lt;code&gt;range&lt;/code&gt;（按区间）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;度量（Metric）聚合&lt;/strong&gt;：对组内文档算统计——&lt;code&gt;avg/sum/min/max/stats/cardinality&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;71-实例员工数据统计&#34;&gt;7.1 实例：员工数据统计&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GET /megacorp/employee/_search
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;size&amp;#34;&lt;/span&gt;: 0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;aggs&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;by_interest&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;              &lt;span style=&#34;color:#75715e&#34;&gt;# 桶：按兴趣分组&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;terms&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;field&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;interests&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;aggs&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;avg_age&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;              &lt;span style=&#34;color:#75715e&#34;&gt;# 嵌套度量：每组平均年龄&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;avg&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;field&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;age&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[&amp;#34;全部员工文档&amp;#34;] --&amp;gt;|&amp;#34;terms 桶 by_interest&amp;#34;| B1[&amp;#34;sports 组&amp;#34;]
    A --&amp;gt; B2[&amp;#34;music 组&amp;#34;]
    A --&amp;gt; B3[&amp;#34;forestry 组&amp;#34;]
    B1 --&amp;gt; C1[&amp;#34;avg_age = 28.5&amp;#34;]
    B2 --&amp;gt; C2[&amp;#34;avg_age = 31.2&amp;#34;]
    B3 --&amp;gt; C3[&amp;#34;avg_age = 35.0&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;72-要点&#34;&gt;7.2 要点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;size: 0&lt;/code&gt;&lt;/strong&gt;：只要聚合不要文档，省掉无用传输；&lt;/li&gt;
&lt;li&gt;聚合只能跑在 &lt;code&gt;keyword&lt;/code&gt;/数值/日期等&lt;strong&gt;精确值字段&lt;/strong&gt;上——在 &lt;code&gt;text&lt;/code&gt; 字段上聚合会失败或慢到崩溃（需要 fielddata，默认关闭，这是个性能地雷）；&lt;/li&gt;
&lt;li&gt;高基数 &lt;code&gt;terms&lt;/code&gt; 聚合（如按 userId 分桶）吃内存，新版有 circuit breaker 兜底；&lt;/li&gt;
&lt;li&gt;近似聚合是 ES 的特色：&lt;code&gt;cardinality&lt;/code&gt;（去重计数）和 &lt;code&gt;percentiles&lt;/code&gt;（百分位）都是&lt;strong&gt;近似算法&lt;/strong&gt;，用微小误差换海量数据下的可用性。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八关系建模es-不是数据库&#34;&gt;八、关系建模：ES 不是数据库&lt;/h2&gt;
&lt;p&gt;书里最&amp;quot;劝退&amp;quot;也最重要的一章：ES 没有 join。建模关系的四种方式按推荐顺序：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;方式&lt;/th&gt;
					&lt;th&gt;思路&lt;/th&gt;
					&lt;th&gt;代价&lt;/th&gt;
					&lt;th&gt;适用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;反规范化（Denormalize）&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;把关联数据冗余进每个文档&lt;/td&gt;
					&lt;td&gt;数据重复、更新要改多处&lt;/td&gt;
					&lt;td&gt;首选，读多写少&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;应用层 join&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;查两次，在代码里拼接&lt;/td&gt;
					&lt;td&gt;多一次网络往返&lt;/td&gt;
					&lt;td&gt;一对多且&amp;quot;多&amp;quot;侧很大&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;nested 对象&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;对象数组整体索引，保持内部关联&lt;/td&gt;
					&lt;td&gt;查询稍慢，更新整文档重建&lt;/td&gt;
					&lt;td&gt;对象数组（如文章的评论列表）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;parent-child（join 字段）&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;父子文档独立存储，同分片关联&lt;/td&gt;
					&lt;td&gt;查询开销最大&lt;/td&gt;
					&lt;td&gt;子文档频繁独立更新&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;默认答案永远是先反规范化&lt;/strong&gt;。搜索系统的哲学是&amp;quot;用写入时的冗余，换查询时的简单&amp;quot;——磁盘便宜，join 昂贵。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九集群管理与运维要点&#34;&gt;九、集群管理与运维要点&lt;/h2&gt;
&lt;p&gt;最后一部分面向生产：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;节点角色分工&lt;/strong&gt;：master 节点管集群元数据（建议 3 个专职 master 防脑裂）、data 节点存数据、协调节点转发请求。大集群应该角色分离。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;脑裂与 minimum_master_nodes&lt;/strong&gt;：网络分区时两个子集群各自选主 = 数据写烂。经典配置是 &lt;code&gt;master 节点数 / 2 + 1&lt;/code&gt;（新版本的集群选举机制已自动化）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分片规划&lt;/strong&gt;：分片不是越多越好——每个分片都有固定开销（文件句柄、内存、段管理）。单分片控制在几十 GB 量级、节点堆内存 32GB 以内（压指针上限）、堆内存不超过物理内存一半（另一半留给文件系统缓存）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;监控集群健康&lt;/strong&gt;：&lt;code&gt;green/yellow/red&lt;/code&gt; + &lt;code&gt;hot_threads&lt;/code&gt; + &lt;code&gt;cat&lt;/code&gt; API 家族。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;升级与备份&lt;/strong&gt;：滚动升级逐个节点来；快照（snapshot）到 S3/HDFS 做备份。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十全书知识地图&#34;&gt;十、全书知识地图&lt;/h2&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    CORE[&amp;#34;倒排索引&amp;lt;br/&amp;gt;（一切的根基）&amp;#34;]
    CORE --&amp;gt; WRITE[&amp;#34;写入链路&amp;lt;br/&amp;gt;refresh/translog/merge&amp;lt;br/&amp;gt;→ 近实时 + 不丢数据&amp;#34;]
    CORE --&amp;gt; SEARCH[&amp;#34;搜索&amp;lt;br/&amp;gt;Query/Filter + bool 组合&amp;lt;br/&amp;gt;TF-IDF 相关性算分&amp;#34;]
    CORE --&amp;gt; AGG[&amp;#34;聚合&amp;lt;br/&amp;gt;桶 × 度量嵌套&amp;#34;]
    WRITE --&amp;gt; DIST[&amp;#34;分布式&amp;lt;br/&amp;gt;分片路由 scatter-gather&amp;lt;br/&amp;gt;主副本容灾&amp;#34;]
    SEARCH --&amp;gt; LANG[&amp;#34;语言处理&amp;lt;br/&amp;gt;分析器/纠错/输入即搜&amp;#34;]
    SEARCH --&amp;gt; MODEL[&amp;#34;建模&amp;lt;br/&amp;gt;反规范化优先&amp;#34;]
    DIST --&amp;gt; OPS[&amp;#34;运维&amp;lt;br/&amp;gt;健康监控/分片规划/防脑裂&amp;#34;]
    style CORE fill:#e1f5e1&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;如果只能记住三句话：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;一切性能与行为的答案都在倒排索引里&lt;/strong&gt;：不可变段决定了 NRT，分词决定了查不查得到，keyword/text 之分决定了能不能聚合；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;query 算分、filter 缓存&lt;/strong&gt;——写任何查询前先想这一条；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分片是分布式的原子&lt;/strong&gt;：路由公式决定了主分片数不能改，副本决定了读吞吐和容灾。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;参考资料：Clinton Gormley, Zachary Tong. 《Elasticsearch: The Definitive Guide》. O&amp;rsquo;Reilly, 2015. 中文版：&lt;a href=&#34;https://github.com/looly/elasticsearch-definitive-guide-cn&#34;&gt;elasticsearch-definitive-guide-cn&lt;/a&gt;（looly 等译）。&lt;/em&gt;&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
