<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Jhon Guzmán - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Jhon Guzmán - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/cn/search-labs/author/jhon-guzman</link>
    </image>
    <link>https://www.elastic.co/cn/search-labs/author/jhon-guzman</link>
    <atom:link href="https://www.elastic.co/cn/search-labs/rss/author/jhon-guzman.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[cn]]></language>
    <lastBuildDate>Tue, 22 Sep 2026 23:47:49 GMT</lastBuildDate>
  <item>
    <title><![CDATA[使用判断列表评估搜索查询的相关性]]></title>
    <description><![CDATA[针对在 Elasticsearch 中开展可扩展的搜索测试，探究如何构建判定列表以客观评估搜索查询相关性，并提升召回率等性能指标。]]></description>
    <content:encoded><![CDATA[<p>从事搜索引擎开发的工程师们常常会遇到同一个问题：业务团队对某次特定搜索结果并不满意，因为他们期望排在搜索结果首位的文档，实际却出现在结果列表的第三或第四位。</p><p>然而，当你解决这一问题时，却可能因无法手动测试所有情况而不经意间破坏其他查询的功能。但你或你的 QA 团队该如何测试，以确认某一项查询的改动是否会对其他查询产生连锁反应呢？或者更关键的是，你们要如何确保所作的改动确实优化了某项查询呢？</p><h2>转向系统性评估</h2><p>这个时候，判断列表就可以派上用场。与其在每次更改时依赖手动和主观测试，不如定义一组与业务案例相关的固定查询及其相关结果。</p><p>这一组（测试用例或数据）将成为基准参照。每次实施改动时，你都用它来评估搜索效果是否确实得到了提升。</p><p>这种方法的价值在于：</p><ul><li><p><strong>消除不确定性</strong>：无需再费心猜测所做的更改是否会影响其他查询；数据会直接告诉你答案。</p></li><li><p><strong>停止人工测试</strong>：一旦判定集被记录下来，测试便会自动执行。</p></li><li><p><strong>佐证更改</strong>：你可以展示出明确的指标，以佐证某项更改所带来的益处。</p></li></ul><h2>如何开始建立判断列表</h2><p>最简单的开始方式之一是获取具有代表性的查询，并手动选择相关文件。有两种方法可以列出此列表：</p><ul><li><p><strong>二元判断：</strong>与查询关联的每一份文档都会被赋予一个<strong>简单标签</strong>：<em>相关</em>（通常标注分数为“1”）和不相关（标注分数为“0”）。</p></li><li><p><strong>分级判断：</strong>在此情境下，每份文档会依据不同等级获得相应分数。例如：采用 0 至 4 分的评分量表，类似于<a href="https://en.wikipedia.org/wiki/Likert_scale">李克特量表</a>，其中 0 分表示“完全不相关”，4 分表示“完全相关”，中间还设有“相关”“有点相关”等不同程度表述。</p></li></ul><p>当搜索意图具有明确界限时，二元判断（是/否）十分奏效，即判断该文档是否应出现在搜索结果中？</p><p>当存在模糊地带时，分级判断更为实用：某些结果相较于其他结果更优，因此你可以将结果划分为“优秀”“良好”和“毫无价值”等不同等级，并运用能体现结果排序权重及用户反馈的评估指标。然而，分级量表也存在弊端：不同评审者对评分等级的使用方式可能存在差异，这会导致判断结果的一致性降低。并且，由于分级指标对高分赋予了更大的权重，即便是一个微小的改动（比如将某项评分从 4 分改为 3 分），也可能在指标上引发远超评审者预期的巨大波动。这种额外引入的主观性使得分级判断结果更具干扰性，且随时间推移愈发难以把控。</p><h2>我需要自己对文件分类吗？</h2><p>不一定，因为有多种不同方法创建判定列表，且每种方法各有其优缺点：</p><ul><li><p><strong>明确判断：</strong>在这种情况下，领域专家会逐一审阅每个查询/文档，并手动判定其相关性（或相关程度）。尽管此方法能确保质量并实现把控，但其可扩展性较差。</p></li><li><p><strong>隐式判断：</strong>采用这种方法时，你会依据真实用户行为（如点击量、跳出率、购买行为等）来推断相关文档。此方法可实现数据的自动收集，但可能存在偏差。例如，用户往往更倾向于点击排名靠前的结果，即便这些结果并不相关。</p></li><li><p><strong>AI 生成的判断：</strong>最后这种方法是借助模型（如 LLM）自动评估查询和文档，人们通常称之为<a href="https://en.wikipedia.org/wiki/LLM-as-a-Judge">LLM 陪审团</a>。其优势在于速度快且易于扩展，不过数据质量取决于所用模型的性能，以及大语言模型训练数据与您业务<a href="http://interests.as/">需求</a>的契合程度。与人工评分一样，LLM 评审团也可能引入自身偏见或出现前后不一致的情况，因此，必须对照一小部分可信判断结果来验证其输出结果。LLM 模型本质上具有概率性，所以即便将<a href="https://www.ibm.com/think/topics/llm-temperature">温度</a>参数设置为 0，也常见同一结果被 LLM 模型给出不同评分的情况。</p></li></ul><p>以下是一些选择最佳方法来构建判断集的建议：</p><ul><li><p>明确界定哪些仅用户能恰当判断的要素对你而言至关重要（例如价格、品牌、语言、风格以及产品细节等）。如果这些要素至关重要，则至少需针对<em>判断列表</em>中的部分内容获取<strong>明确的判断结果</strong>。</p></li><li><p>当你的搜索引擎已有足够流量时，可运用<strong>隐式判断</strong>，即借助点击量、转化率以及停留时长等指标来洞察使用趋势。不过，你仍需谨慎解读这些数据，将其与显式判断结果进行对比，以规避潜在偏差（例如用户往往更倾向于点击排名靠前的结果，即便排名靠后的结果更具相关性）。</p></li></ul><p>为解决这一问题，位置偏差消除技术会对点击数据进行调整或重新加权，以更准确地反映用户的真实兴趣。以下是一些方法：</p><ul><li><p><strong>结果随机排序：</strong>针对部分用户调整搜索结果的排序，以此估算结果位置对点击量的影响。</p></li><li><p><strong>点击模型</strong>包括<a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking">动态贝叶斯网络 </a><a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking"><strong>DBN</strong></a> 和<a href="https://rsrikant.com/papers/kdd10.pdf">用户浏览模型 </a><a href="https://rsrikant.com/papers/kdd10.pdf"><strong>UBM</strong></a>。这些统计模型会借助滚动行为、停留时长、点击顺序以及返回结果页等模式，来估算用户点击行为反映真实兴趣（而非仅受结果位置影响）的概率。</p></li></ul><h2>示例：电影评分应用</h2><h3>准备工作</h3><p>要运行此示例，需要一个正在运行的<a href="https://www.elastic.co/downloads/elasticsearch">本地</a>或部署在 <a href="https://www.elastic.co/cloud/cloud-trial-overview">Elastic Cloud</a> 上（托管或无服务器）的 Elasticsearch 8.x 集群，以及访问 <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis">REST API</a> 或 Kibana 的权限。</p><p>想象有一款应用程序，用户可以在其中上传自己对电影的看法，还可以搜索要观看的电影。由于文本由用户自己撰写，因此可能存在拼写错误和表达方式上的多种差异。因此，搜索引擎必须能够解读这种多样性，并为用户提供有用的结果。</p><p>为能在不影响整体搜索行为的前提下对查询进行迭代优化，贵公司业务团队基于最常执行的搜索查询，创建了以下二元判断集：</p><p>查询</p><p>DocID</p><p>文本</p><p>迪卡普里奥的表演</p><p>doc1</p><p>迪卡普里奥在《荒野猎人》中的表演令人惊叹。</p><p>迪卡普里奥的表演</p><p>doc2</p><p>《盗梦空间》中，莱昂纳多·迪卡普里奥饰演了他最具标志性的角色之一。</p><p>迪卡普里奥的表演</p><p>doc3</p><p>布拉德·皮特在这部犯罪惊悚片中表现出色。</p><p>迪卡普里奥的表演</p><p>doc4</p><p>一部充满惊险动作、视觉效果惊艳的冒险大片。</p><p>让人热泪盈眶的悲伤电影</p><p>doc5</p><p>这是一个令人心碎的关于爱与失去的故事，让我哭了好几个小时。</p><p>让人热泪盈眶的悲伤电影</p><p>doc6</p><p>有史以来最催泪的电影之一，记得带上纸巾！</p><p>让人热泪盈眶的悲伤电影</p><p>doc7</p><p>让你捧腹大笑的轻松喜剧</p><p>让人热泪盈眶的悲伤电影</p><p>doc8</p><p>一部充满动作与激情的科幻史诗巨作。</p><p>正在创建索引：</p>PUT movies
{
  "mappings": {
    "properties": {
      "text": {
        "type": "text"
      }
    }
  }
}<p>批量请求：</p>POST /movies/_bulk
{ "index": { "_id": "doc1" } }
{ "text": "DiCaprio performance in The Revenant was breathtaking." }
{ "index": { "_id": "doc2" } }
{ "text": "Inception shows Leonardo DiCaprio in one of his most iconic roles." }
{ "index": { "_id": "doc3" } }
{ "text": "Brad Pitt delivers a solid performance in this crime thriller." }
{ "index": { "_id": "doc4" } }
{ "text": "An action-packed adventure with stunning visual effects." }
{ "index": { "_id": "doc5" } }
{ "text": "A heartbreaking story of love and loss that made me cry for hours." }
{ "index": { "_id": "doc6" } }
{ "text": "One of the saddest movies ever made -- bring tissues!" }
{ "index": { "_id": "doc7" } }
{ "text": "A lighthearted comedy that will make you laugh." }
{ "index": { "_id": "doc8" } }
{ "text": "A science-fiction epic full of action and excitement." }<p>以下是该应用程序正在使用的 Elasticsearch 查询：</p>GET movies/_search
{
 "query": {
   "match": {
     "text": {
       "query": "DiCaprio performance",
       "minimum_should_match": "100%"
     }
   }
 }
}<h3>从判断到指标</h3><p>就其本身而言，判断列表并不提供太多信息；它们只是我们查询结果的期望。它们真正的优势在于，当我们使用它们来计算客观指标以衡量我们的搜索性能时。</p><p>如今，大多数常用指标包含</p><ul><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-precision"><strong>精度</strong></a><strong>：</strong>衡量所有搜索结果中真正相关的结果比例。</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-recall"><strong>召回率</strong></a><strong>：</strong>衡量搜索引擎在检索出的 x 个结果中，找到的相关结果所占的比例。</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_discounted_cumulative_gain_dcg"><strong>折损累积增益（DCG）</strong></a><strong>：</strong>用于衡量结果排序的质量，该指标基于最相关的结果应排在前列这一原则进行评估。</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_mean_reciprocal_rank"><strong>平均倒数排名（MRR）</strong></a>：用于衡量首个相关结果所处的排名位置情况 。在列表中越靠前，其分数就越高。</p></li></ul><p>以同样的电影评分应用程序为例，我们将计算召回率指标，看看我们的查询是否遗漏了任何信息。</p><p>在 Elasticsearch 中，我们可以通过<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval">排名评估 API</a>，使用<em>判断列表</em>来计算指标。该 API 将判断列表、查询以及想要评估的指标作为输入，并返回一个数值，该数值是对查询结果与判断列表进行对比后得出的结果。</p><p>让我们针对已提出的这两个查询运行判定列表：</p>POST /movies/_rank_eval
{
 "requests": [
   {
     "id": "dicaprio-performance",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "DiCaprio performance",
             "minimum_should_match": "100%"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc1",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc2",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc3",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc4",
         "rating": 0
       }
     ]
   },
   {
     "id": "sad-movies",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "sad movies that make you cry",
             "minimum_should_match": "100%"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc5",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc6",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc7",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc8",
         "rating": 0
       }
     ]
   }
 ],
 "metric": {
   "recall": {
     "k": 10,
     "relevant_rating_threshold": 1
     }
 }
}<p>我们将向 rank_eval 发送两个请求：一个针对莱昂纳多·迪卡普里奥查询，另一个针对悲伤电影查询每个请求均包含一个查询及其对应的判定列表（评分）。我们无需对所有文档进行评分，因为未纳入评分范围的文档将被视为未作判定。在进行计算时，召回率仅考虑“相关文档集”，即那些在评分中被认定为相关的文档。</p><p>在此情形下，针对莱昂纳多·迪卡普里奥的查询召回率为 1，而悲伤电影查询的召回率为 0。这意味着对于第一个查询，我们能够获取到所有相关结果，而第二个查询则未获取到任何相关结果。因此，平均召回率为 0.5。</p>{
 "metric_score": 0.5,
 "details": {
   "dicaprio-performance": {
     "metric_score": 1,
     "unrated_docs": [],
     "hits": [
       {
         "hit": {
           "_index": "movies",
           "_id": "doc1",
           "_score": 2.4826927
         },
         "rating": 1
       },
       {
         "hit": {
           "_index": "movies",
           "_id": "doc2",
           "_score": 2.0780432
         },
         "rating": 1
       }
     ],
     "metric_details": {
       "recall": {
         "relevant_docs_retrieved": 2,
         "relevant_docs": 2
       }
     }
   },
   "sad-movies": {
     "metric_score": 0,
     "unrated_docs": [],
     "hits": [],
     "metric_details": {
       "recall": {
         "relevant_docs_retrieved": 0,
         "relevant_docs": 2
       }
     }
   }
 },
 "failures": {}
}<p>或许我们对 <strong>minimum_should_match</strong> 参数设置得过于严苛了，因为要求查询中的所有词汇都必须在文档中出现，这很可能会导致我们遗漏掉一些相关结果。不妨去掉 <strong>minimum_should_match</strong> 参数，这样只要文档中包含查询语句里的任意一个词汇，该文档就会被视为相关结果。</p>POST /movies/_rank_eval
{
 "requests": [
   {
     "id": "dicaprio-performance",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "DiCaprio performance"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc1",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc2",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc3",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc4",
         "rating": 0
       }
     ]
   },
   {
     "id": "sad-movies",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "sad movies that make you cry"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc5",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc6",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc7",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc8",
         "rating": 0
       }
     ]
   }
 ],
 "metric": {
   "recall": {
     "k": 10,
     "relevant_rating_threshold": 1
     }
 }
}<p>如你所见，通过在两个查询中的其中一个里移除 <strong>minimum_should_match</strong> 参数，现在两个查询的平均召回率都达到了 1。</p>{
  "metric_score": 1,
  "details": {
    "dicaprio-performance": {
      "metric_score": 1,
      "unrated_docs": [],
      "hits": [
        {
          "hit": {
            "_index": "movies",
            "_id": "doc1",
            "_score": 2.0661702
          },
          "rating": 1
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc3",
            "_score": 0.732218
          },
          "rating": 0
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc2",
            "_score": 0.6271719
          },
          "rating": 1
        }
      ],
      "metric_details": {
        "recall": {
          "relevant_docs_retrieved": 2,
          "relevant_docs": 2
        }
      }
    },
    "sad-movies": {
      "metric_score": 1,
      "unrated_docs": [],
      "hits": [
        {
          "hit": {
            "_index": "movies",
            "_id": "doc7",
            "_score": 2.1307156
          },
          "rating": 0
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc5",
            "_score": 1.3160692
          },
          "rating": 1
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc6",
            "_score": 1.190063
          },
          "rating": 1
        }
      ],
      "metric_details": {
        "recall": {
          "relevant_docs_retrieved": 2,
          "relevant_docs": 2
        }
      }
    }
  },
  "failures": {}
}<p>总而言之，移除 minimum_should_match: 100% 这一条件后，我们得以使两个查询均实现完美召回率。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaf4f08a8a2915180/6a170df61949f76cbfe7aaba/24d055da4348c63827ba7046fe8cafb6f47cadd8-546x628.png" alt="" /><p>我们做到了！对不对？</p><p>没那么快！</p><p>通过提升召回率，我们能够获取到更广泛的结果范围。然而，每一次调整都意味着需要权衡取舍。这正是为何要定义完整的测试用例，并运用不同指标来评估各项更改的原因。</p><p>使用判断列表和指标可以防止您在进行更改时盲目行事，因为现在您有数据可以支持这些更改。验证不再是手动和重复的，您可以在多个用例中测试您的更改。此外，A/B 测试允许您实时测试哪种配置最适合您的用户和业务案例，从而实现从技术指标到实际指标的完整循环。</p><h2>使用判断列表的最终建议</h2><p>运用判定列表开展工作，不仅关乎评估测量，更在于构建一个能让你自信迭代优化的框架。为实现这一目标，可遵循以下建议：</p><ol><li><p><strong>从小处着手，但一定要开始行动。</strong>你无需准备 10000 个查询，且每个查询都配有 50 个判断列表。你只需找出 5 到 10 个对业务场景最为关键的查询，并明确你期望在结果顶部看到的文档即可。这已经能为你提供一个基础。通常，你应优先从热门查询以及无结果的查询入手开展工作。你也可以先使用像精确率这样易于配置的指标进行测试，然后再逐步尝试更复杂的指标。</p></li><li><p><strong>与用户核实。</strong>在生产环境中通过 A/B 测试对数据指标进行补充验证。如此一来，你便能知晓那些在指标上表现良好的更改是否也切实产生了实际影响。</p></li><li><p><strong>保持列表有效性。</strong>你的商业案例会不断变化，关键问题也会随之变化。定期更新判断以反映新的需求。</p></li><li><p><strong>使其成为流程的一部分。</strong>将判断列表整合到开发管道之中。确保每次配置更改、同义词添加或文本分析操作，都能自动对照基础列表进行验证。</p></li><li><p><strong>将技术知识与战略相结合。</strong>不要仅仅满足于衡量精确率或召回率等技术指标。要利用评估结果为业务成果提供决策依据。</p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/judgment-lists-search-query-relevance-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/judgment-lists-search-query-relevance-elasticsearch</guid>
    <category><![CDATA[相关性]]></category>
    <category><![CDATA[在 Elastic 内部]]></category>
    <dc:creator><![CDATA[Jhon Guzmán]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcadfd2fb1cc95b4c/6a170df7acf0887798be9bd0/25478d0ffb228afd5d65d82312998ec1c299c565-700x490.png" length="0" type="image/png"/>
    <pubDate>Thu, 11 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[介绍 Kibana 中的 Elasticsearch 查询规则用户界面]]></title>
    <description><![CDATA[了解如何使用 Elasticsearch 查询规则用户界面，在 Kibana 中使用可定制的规则集从搜索查询中添加或排除文档，而不影响有机排名。]]></description>
    <content:encoded><![CDATA[<p>搜索引擎的工作就是返回相关结果。然而，有些业务需求并不限于此，比如突出销售、优先考虑季节性产品或展示赞助项目，而开发人员不可能总是在搜索查询中做到这一点。</p><p>此外，这些用例通常具有时间敏感性，而经历典型的开发阶段（创建代码分支，然后等待新版本发布）是一个耗时的过程。</p><p>那么，如果我们只需调用 API，或者在 Kibana 中点击几下就能完成整个过程，那会怎样呢？</p><h2>查询规则用户界面</h2><p>Elasticsearch 8.10 引入了<a href="https://www.elastic.co/blog/introducing-query-rules-elasticsearch-8-10"><strong>查询规则</strong></a>和<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/retrievers/rule-retriever"><strong>规则检索器</strong></a>。这些工具旨在根据规则在不影响有机结果排名的情况下将<a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-pinned-query"><em>钉入结果</em></a>注入查询。它们只是以声明式的简单方式在结果之上添加业务逻辑。</p><p>查询规则的一些常见用例包括</p><ul><li><p><strong>突出显示促销列表或销售</strong>：在顶部显示促销或赞助商品。</p></li><li><p><strong>根据上下文或地理位置排除</strong>：当当地法规不允许显示某些项目时，隐藏这些项目。</p></li><li><p><strong>优先处理关键结果</strong>：确保热门搜索或固定搜索始终排在前面，无论有机搜索排名如何。</p></li></ul><p>要访问界面并与这些工具互动，需要点击 Kibana 侧边菜单，然后转到相关性下的<strong>查询规则</strong> <strong>：</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltac12541cddd58e36/6a170853a29299941cd00fc2/242e33e89d1a07ffa0e76009c46b3a9236722741-458x1010.png" alt="在相关性下访问 Elasticsearch 中的查询规则" /><p>查询规则菜单弹出后，点击<strong>创建第一个规则集：</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcc28329c0f3c3aa9/6a17085547d49c67e22d893b/30b3a91bbbf243d314cf38298e01ca5cff784430-1600x945.png" alt="在 Elasticsearch 中创建第一个查询规则集" /><p>接下来，您需要为规则集命名。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb37d271297a4f148/6a170856a29299782cd00fc6/26c5462f88678867776f933b5655ca0df0d72a16-708x446.png" alt="在 Elasticsearch 中命名查询规则集" /><p>定义每条规则的表格有三个关键部分：</p><ul><li><p><strong>标准</strong>：适用规则必须满足的条件。例如，"当 query_string 字段包含<em>Christmas</em>值时 "或 "当 country 字段为<em>CO 时"。</em></p></li><li><p><strong>行动</strong>：这是您希望在条件满足时发生的事情。它可以被固定（将文档固定到顶部结果）或排除（隐藏文档）。</p></li><li><p><strong>元数据</strong>：这些字段在查询运行时会随查询一起出现。它们可以包括用户信息（如位置或语言）以及搜索数据（query_string）。这些值是标准用于决定是否应用规则的值。</p></li></ul><h2>例如：热门项目</h2><p>假设我们有一个电子商务网站，上面有不同的商品。在查看这些指标时，我们注意到在游戏机类别中，"DualShock 4 无线控制器 "是销售量最大的商品之一，尤其是当用户搜索关键词 "PS4 "或 "PlayStation 4 "时。因此，我们决定在用户搜索这些关键词时，将该产品放在搜索结果的顶部。</p><p>首先，让我们使用批量 API 请求为每个项目的文档建立索引：</p>POST _bulk
{ "index": { "_index": "products", "_id": "1" } }
{ "id": "1", "name": "PlayStation 4 Slim 1TB", "category": "console", "brand": "Sony", "price": 1200 }
{ "index": { "_index": "products", "_id": "2" } }
{ "id": "2", "name": "DualShock 4 Wireless Controller", "category": "accessory", "brand": "Sony", "price": 250 }
{ "index": { "_index": "products", "_id": "3" } }
{ "id": "3", "name": "PlayStation 4 Camera", "category": "accessory", "brand": "Sony", "price": 200 }
{ "index": { "_index": "products", "_id": "4" } }
{ "id": "4", "name": "PlayStation 4 VR Headset", "category": "accessory", "brand": "Sony", "price": 900 }
{ "index": { "_index": "products", "_id": "5" } }
{ "id": "5", "name": "Charging Station for DualShock 4", "category": "accessory", "brand": "Sony", "price": 80 }<p>如果我们不干预查询，该项目通常会出现在第四位。问题是这样的</p>GET products/_search
{
 "query": {
   "match": {
     "name": "PlayStation 4"
   }
 }
}<p>结果如下</p>{
 "took": 1,
 "timed_out": false,
 "_shards": {
   "total": 1,
   "successful": 1,
   "skipped": 0,
   "failed": 0
 },
 "hits": {
   "total": {
     "value": 5,
     "relation": "eq"
   },
   "max_score": 0.6973252,
   "hits": [
     {
       "_index": "products",
       "_id": "3",
       "_score": 0.6973252,
       "_source": {
         "id": "3",
         "name": "PlayStation 4 Camera",
         "category": "accessory",
         "brand": "Sony",
         "price": 200
       }
     },
     {
       "_index": "products",
       "_id": "1",
       "_score": 0.6260078,
       "_source": {
         "id": "1",
         "name": "PlayStation 4 Slim 1TB",
         "category": "console",
         "brand": "Sony",
         "price": 1200
       }
     },
     {
       "_index": "products",
       "_id": "4",
       "_score": 0.6260078,
       "_source": {
         "id": "4",
         "name": "PlayStation 4 VR Headset",
         "category": "accessory",
         "brand": "Sony",
         "price": 900
       }
     },
     {
       "_index": "products",
       "_id": "2",
       "_score": 0.08701137,
       "_source": {
         "id": "2",
         "name": "DualShock 4 Wireless Controller",
         "category": "accessory",
         "brand": "Sony",
         "price": 250
       }
     },
     {
       "_index": "products",
       "_id": "5",
       "_score": 0.07893815,
       "_source": {
         "id": "5",
         "name": "Charging Station for DualShock 4",
         "category": "accessory",
         "brand": "Sony",
         "price": 80
       }
     }
   ]
 }
}<p>让我们创建一个查询规则来改变这种情况。首先，让我们像这样把它添加到规则集中：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1576d4f4a2e60548/6a170858cdacbfccb07d298d/fdc42646fb3e76a09bca7d19047a76efe343f7a2-1600x650.png" alt="如何在 Elasticsearch 中编辑查询规则集" /><p>或相应的<a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-query-rules-put-ruleset">API 请求</a>：</p>PUT _query_rules/my-rules
{
  "rules": [
    {
      "rule_id": "rule-1232",
      "type": "pinned",
      "criteria": [
        {
          "type": "exact",
          "metadata": "query_string",
          "values": [
            "PS4",
            "PlayStation 4"
          ]
        }
      ],
      "actions": {
        "docs": [
          {
            "_index": "products",
            "_id": "2"
          }
        ]
      }
    }
  ]
}<p>要在查询中使用<strong>规则集 </strong>，我们必须使用查询规则类型。这种查询主要由两部分组成：</p>GET /products/_search
{
 "retriever": {
   "rule": {
     "retriever": {
       "standard": {
         "query": {
           "match": { "name": "PlayStation 4" }
         }
       }
     },
     "match_criteria": {
       "query_string": "PlayStation 4"
     },
     "ruleset_ids": ["my-rules"]
   }
 }
}<ul><li><p><strong>匹配标准</strong>：这些是用于与用户查询进行比较的元数据。在本例中，当 query_string 字段的值为 "PlayStation 4 "时，规则集被激活。</p></li><li><p><strong>query</strong>：实际查询，用于搜索和获取有机结果。</p></li></ul><p>这样，首先运行有机查询，然后 Elasticsearch 应用规则集中的规则：</p>{
 "took": 17,
 "timed_out": false,
 "_shards": {
   "total": 1,
   "successful": 1,
   "skipped": 0,
   "failed": 0
 },
 "hits": {
   "total": {
     "value": 5,
     "relation": "eq"
   },
   "max_score": 1.7014122e+38,
   "hits": [
     {
       "_index": "products",
       "_id": "2",
       "_score": 1.7014122e+38,
       "_source": {
         "id": "2",
         "name": "DualShock 4 Wireless Controller",
         "category": "accessory",
         "brand": "Sony",
         "price": 250
       }
     },
     {
       "_index": "products",
       "_id": "3",
       "_score": 0.6973252,
       "_source": {
         "id": "3",
         "name": "PlayStation 4 Camera",
         "category": "accessory",
         "brand": "Sony",
         "price": 200
       }
     },
     {
       "_index": "products",
       "_id": "1",
       "_score": 0.6260078,
       "_source": {
         "id": "1",
         "name": "PlayStation 4 Slim 1TB",
         "category": "console",
         "brand": "Sony",
         "price": 1200
       }
     },
     {
       "_index": "products",
       "_id": "4",
       "_score": 0.6260078,
       "_source": {
         "id": "4",
         "name": "PlayStation 4 VR Headset",
         "category": "accessory",
         "brand": "Sony",
         "price": 900
       }
     },
     {
       "_index": "products",
       "_id": "5",
       "_score": 0.07893815,
       "_source": {
         "id": "5",
         "name": "Charging Station for DualShock 4",
         "category": "accessory",
         "brand": "Sony",
         "price": 80
       }
     }
   ]
 }
}<h2>示例：基于用户的元数据</h2><p>查询规则的另一个有趣应用是使用元数据，根据用户或网页的上下文信息显示特定文档。</p><p>例如，假设我们想根据用户的忠诚度（用数值表示）来突出显示商品或定制销售。</p><p>我们可以直接将这些元数据导入查询，这样当所述值满足特定条件时，规则就会激活。</p><p>首先，我们将为一份只有忠诚度高的用户才能看到的文档建立索引：</p>POST _bulk
{ "index": { "_index": "products", "_id": "6" } }
{ "id": "6", "name": "PlayStation Plus Deluxe Card - 12 months", "category": "membership", "brand": "Sony", "price": 300 }<p>现在，让我们在同一规则集内创建一条新规则，这样当忠诚度_级别等于或高于 80 时，项目就会出现在结果的顶部。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt158578005df8c76d/6a17085aab7f086dc0db9de3/58de12dff93305440608f51465462fcc68653a08-1421x496.png" alt="如何在 Elasticsearch 中编辑查询规则集" /><p>保存规则和规则集。</p><p>以下是相应的 REST 请求：</p>PUT _query_rules/my-rules
{
  "rules": [
    {
      "rule_id": "pin-premiun-user",
      "type": "pinned",
      "criteria": [
        {
          "type": "gte",
          "metadata": "loyalty_level",
          "values": [
            80
          ]
        }
      ],
      "actions": {
        "docs": [
          {
            "_index": "products",
            "_id": "6"
          }
        ]
      }
    }
  ]
}<p>现在，在运行查询时，我们需要在元数据中包含新参数<strong>loyalty_level </strong>。如果满足规则中的条件，新文档将出现在结果的顶部。</p><p>例如，在发送忠诚度级别为 80 的查询时：</p>POST /products/_search
{
  "retriever": {
    "rule": {
      "retriever": {
        "standard": {
          "query": {
            "match": {
              "name": "PlayStation"
            }
          }
        }
      },
      "match_criteria": {
        "query_string": "PlayStation",
        "loyalty_level": 80
      },
      "ruleset_ids": ["my-rules"]
    }
  }
}<p>我们将在结果上方看到忠诚度文件：</p>{
  "took": 31,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 1.7014122e+38,
    "hits": [
      {
        "_index": "products",
        "_id": "6",
        "_score": 1.7014122e+38,
        "_source": {
          "id": "6",
          "name": "PlayStation Plus Deluxe Card - 12 months",
          "category": "membership",
          "brand": "Sony",
          "price": 300
        }
      },
      {
        "_index": "products",
        "_id": "3",
        "_score": 0.5054567,
        "_source": {
          "id": "3",
          "name": "PlayStation 4 Camera",
          "category": "accessory",
          "brand": "Sony",
          "price": 200
        }
      },
      {
        "_index": "products",
        "_id": "1",
        "_score": 0.45618832,
        "_source": {
          "id": "1",
          "name": "PlayStation 4 Slim 1TB",
          "category": "console",
          "brand": "Sony",
          "price": 1200
        }
      },
      {
        "_index": "products",
        "_id": "4",
        "_score": 0.45618832,
        "_source": {
          "id": "4",
          "name": "PlayStation 4 VR Headset",
          "category": "accessory",
          "brand": "Sony",
          "price": 900
        }
      }
    ]
  }
}<p>在下面的例子中，由于忠诚度等级为 70，因此不符合规则，物品不应出现在顶部：</p>POST /products/_search
{
  "retriever": {
    "rule": {
      "retriever": {
        "standard": {
          "query": {
            "match": {
              "name": "PlayStation"
            }
          }
        }
      },
      "match_criteria": {
        "query_string": "PlayStation",
        "loyalty_level": 70
      },
      "ruleset_ids": ["my-rules"]
    }
  }
}<p>结果如下：</p>{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 0.5054567,
    "hits": [
      {
        "_index": "products",
        "_id": "3",
        "_score": 0.5054567,
        "_source": {
          "id": "3",
          "name": "PlayStation 4 Camera",
          "category": "accessory",
          "brand": "Sony",
          "price": 200
        }
      },
      {
        "_index": "products",
        "_id": "1",
        "_score": 0.45618832,
        "_source": {
          "id": "1",
          "name": "PlayStation 4 Slim 1TB",
          "category": "console",
          "brand": "Sony",
          "price": 1200
        }
      },
      {
        "_index": "products",
        "_id": "4",
        "_score": 0.45618832,
        "_source": {
          "id": "4",
          "name": "PlayStation 4 VR Headset",
          "category": "accessory",
          "brand": "Sony",
          "price": 900
        }
      },
      {
        "_index": "products",
        "_id": "6",
        "_score": 0.3817649,
        "_source": {
          "id": "6",
          "name": "PlayStation Plus Deluxe Card - 12 months",
          "category": "membership",
          "brand": "Sony",
          "price": 300
        }
      }
    ]
  }
}<h2>例如：立即排除</h2><p>假设我们的<strong>DualShock 4 无线控制器（ID 2）</strong>暂时缺货，无法出售。因此，业务团队决定在此期间将其从搜索结果中删除，而不是手动删除文档或等待某些数据流程启动。</p><p>我们将使用与刚才应用于热门项目类似的过程，但这次我们不选择 "<em>已固定"</em>，而是选择 "<em>排除</em>"。这条规则就像一个黑名单。将条件改为 "<strong>始终"</strong>，这样每次运行查询时，排除都会起作用。</p><p>规则应该是这样的</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt38564c0b7f4a6ee2/6a17085c1949f78692e7a989/f10971e4f1bc9520105111adfa3a476581a27130-1600x623.png" alt="Elasticsearch 中立即排除规则集的示例" /><p>保存规则和规则集以应用更改。以下是相应的 REST 请求：</p>PUT _query_rules/my-rules
{
  "rules": [
    {
      "rule_id": "rule-6358",
      "type": "pinned",
      "criteria": [
        {
          "type": "always"
        }
      ],
      "actions": {
        "docs": [
          {
            "_index": "products",
            "_id": "2"
          }
        ]
      }
    }
  ]
}<p>现在，当我们再次运行查询时，你会发现结果中不再有该项目，尽管之前的规则是将其固定。这是因为<strong>排除结果的优先级高于钉牢结果</strong>。</p>{
 "took": 6,
 "timed_out": false,
 "_shards": {
   "total": 1,
   "successful": 1,
   "skipped": 0,
   "failed": 0
 },
 "hits": {
   "total": {
     "value": 4,
     "relation": "eq"
   },
   "max_score": 2.205655,
   "hits": [
     {
       "_index": "products",
       "_id": "3",
       "_score": 2.205655,
       "_source": {
         "id": "3",
         "name": "PlayStation 4 Camera",
         "category": "accessory",
         "brand": "Sony",
         "price": 200
       }
     },
     {
       "_index": "products",
       "_id": "1",
       "_score": 1.9738505,
       "_source": {
         "id": "1",
         "name": "PlayStation 4 Slim 1TB",
         "category": "console",
         "brand": "Sony",
         "price": 1200
       }
     },
     {
       "_index": "products",
       "_id": "4",
       "_score": 1.9738505,
       "_source": {
         "id": "4",
         "name": "PlayStation 4 VR Headset",
         "category": "accessory",
         "brand": "Sony",
         "price": 900
       }
     },
     {
       "_index": "products",
       "_id": "5",
       "_score": 0.69247496,
       "_source": {
         "id": "5",
         "name": "Charging Station for DualShock 4",
         "category": "accessory",
         "brand": "Sony",
         "price": 80
       }
     }
   ]
 }
}<h2>结论</h2><p><strong>查询规则</strong>使调整相关性变得非常容易，无需修改任何代码。新的<strong>Kibana</strong> <strong>UI </strong>允许在几秒钟内做出这些更改，让您和您的业务团队对搜索结果拥有更多控制权。</p><p>除电子商务外，查询规则还能支持许多其他应用场景：在支持门户中突出显示故障排除指南，在知识库中显示关键的内部文档，在新闻网站中宣传突发事件，或过滤掉过期的职位或内容列表。它们甚至可以执行合规规则，如根据用户角色或地区隐藏受限资料。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-query-rules-ui-introduction</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-query-rules-ui-introduction</guid>
    <category><![CDATA[基础功能]]></category>
    <category><![CDATA[开发者体验]]></category>
    <dc:creator><![CDATA[Jhon Guzmán]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt565ed0eb407e098d/6a17085d8b73cb363d189fb1/1fb10bd31c509cc9b9bb4f71f49970f140e6c36f-1600x945.png" length="0" type="image/png"/>
    <pubDate>Fri, 07 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>