📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入
Easysearch 布尔查询子句重排序(一)|你的 BoolQuery 写法,真的影响性能吗?

从 Easysearch 到 Lucene,查询构建层的 11 条优化规则

INFINI Easysearch 是一款专注于企业级场景的分布式近实时搜索与分析引擎。它以 Apache Lucene 为内核进行了增强,在保持与行业主流搜索协议及开发生态完全兼容的同时,重点强化了安全性、稳定性、压缩率及信创兼容性。


一、开篇:一个常见的误解 #

“must 里面,是不是应该把匹配文档少的条件写在前面?这样能提前过滤掉大量文档,性能更好?”

这个直觉来得很自然,但它是错的

┌─────────────────────────────────────┐
│  用户的直觉:                         │
│  must: [高频词, 低频词] → 慢          │
│  must: [低频词, 高频词] → 快          │
│                                     │
│  实际情况:                          │
│  两种写法性能完全相同!                │
│  Lucene 执行时自动按 cost 排序        │
└─────────────────────────────────────┘

Easysearch 执行时会按 cost 自动重排子句顺序,与你写查询时的顺序无关。不过"子句顺序不重要"并非处处成立,它有一条跟版本挂钩的边界——must/filter 里混入 prefix/wildcard 这类多词查询时,老版本引擎会重新对顺序敏感(详见 第二篇 §八的边界说明)。而且"子句顺序不重要"也不代表"怎么写都一样"——理解引擎自动优化的边界在哪里,才能设计出更合理的查询结构。

本文是系列第一篇,聚焦构建层:从你发出 JSON 到查询进入执行引擎,中间经历了哪些变换?哪些优化在这个阶段完成?哪些要留到执行层?后续三篇将分别深入合取查询的 cost 排序、析取查询的 WAND 剪枝,以及 Block-Max 块级剪枝与实战验证。


二、全景:一次布尔查询的完整旅程 #

先建立一张全局地图,再深入每一层。

举个例子:一条布尔查询就像一个包裹进入工厂流水线,经过三道工序:

  • 第一道(Easysearch 层):质检员检查包裹格式是否合规,缺不缺东西,但不重新排列里面的物品顺序
  • 第二道(Lucene rewrite):工艺师合并重复部件、去掉矛盾组合、把"可选"升级为"必选"——改变的是包裹的内容结构,不是物品顺序
  • 第三道(Scorer 层):调度员拿到最终包裹,按每个部件的"处理成本"自动安排加工顺序——这才是代价排序发生的地方

用技术语言描述,这三道工序对应的是(注意①和②③分属不同阶段):

用户 JSON
   │
   ▼
┌──────────────────────────────────────────┐
│  Easysearch 层(构建层)                   │
│  ① doRewrite() — 递归重写 + 早期终止       │
│  ② applyMinimumShouldMatch              │
│  ③ fixNegativeQueryIfNeeded             │
│  (①在 rewrite 阶段,②③在 doToQuery()内)│
│  职责:结构合法化,不改子句顺序              │
└────────────────┬─────────────────────────┘
                 │ toQuery() → BooleanQuery
                 ▼
┌────────────────────────────────────────────┐
│  Lucene rewrite 层(逻辑重写层)             │
│  ④ BooleanQuery.rewrite()                 │
│  (IndexSearcher 中 rewrite→createWeight) │
│  职责:11条逻辑等价改写,不改结果只改形态       │
└────────────────┬───────────────────────────┘
                 │ createWeight()
                 ▼
┌──────────────────────────────────────────┐
│  Scorer 构造层(执行层)                   │
│  ⑤ ConjunctionDISI:按 cost() 排序 ✅    │
│  ⑥ WANDScorer:按 maxScore 动态重排 ✅    │
│  职责:代价感知,真正的性能优化在这里         │
└────────────────┬─────────────────────────┘
                 │
                 ▼
           执行查询,返回结果

一个关键认知:代价排序发生在第⑤步(Scorer 层)。前两道工序只做逻辑等价改写——合并重复、升级类型、展平嵌套,但不改变查询结果。

本文讲前两层(①~④),后三篇讲第⑤⑥步。


三、Easysearch 层:结构合法化,不碰顺序 #

你发出的 JSON,首先被 Easysearch 的 BoolQueryBuilder 解析成内部的查询对象。这一层做的事情很克制:保证查询结构合法,但不改变子句顺序

3.1 子句是如何被添加的 #

BoolQueryBuilder.doToQuery() 按照固定顺序把子句添加到 Lucene 的 BooleanQuery.Builder 中:

must → mustNot → should → filter

不同类型之间的添加顺序是固定的(无论你的 JSON 里先写 should 还是先写 must),但同一类型内的子句顺序与 JSON 书写顺序一致——这通常不影响性能,因为代价排序发生在更下游的 Scorer 层;唯一的例外见 第二篇 §八:老版本上混入多词查询时,书写顺序仍会起作用。

3.2 三种特殊处理 #

Easysearch 层会做三类结构合法化处理:

doRewrite() 的早期终止

  • 如果整个 BoolQuery 为空(没有任何子句),退化为 MatchAllQueryBuilder(等价于 Lucene 的 MatchAllDocsQuery
  • 如果任何 mustfilter 子句重写后变为 MatchNoneQueryBuilder,整个 BoolQuery 直接返回该 MatchNoneQueryBuilder——不需要继续执行
  • 如果没有 must/filter 子句,但所有 should 子句都重写为 MatchNoneQueryBuilder,整个 BoolQuery 也退化为 MatchNoneQueryBuilder——没有必须匹配的子句,所有可选子句又都匹配零文档,结果必然为空

fixNegativeQueryIfNeeded(): 当查询只有 must_not 子句、没有任何正向匹配条件时,Lucene 的 BooleanQuery 不知道"从哪些文档里排除"。Easysearch 自动插入一个 MatchAllDocsQuery 作为基础集合。该修复受 adjust_pure_negative 开关控制(默认为 true,可设为 false 关闭):

输入:must_not: [term:spam]
处理:加入 MatchAllDocsQuery (作为 FILTER)
输出:filter: [MatchAll] + must_not: [term:spam]
      = "所有文档 除了 spam"

applyMinimumShouldMatch(): 把用户设置的 minimum_should_match 规格字符串(支持整数 "2"、百分比 "75%"、条件式 "3<75%" 等)解析为 int,写入 Lucene 的 BooleanQuery.setMinimumNumberShouldMatch()

总结:**Easysearch 层不改变子句顺序,只做合法化修补。**真正的优化交给下游。


四、Lucene rewrite 层:11 条逻辑等价改写规则 #

查询经过 toQuery() 变成 Lucene 的 BooleanQuery 对象后,会调用 BooleanQuery.rewrite()。这是本文的核心章节。

这一层不做代价排序,而是通过 11 条规则改写查询的形态——去重、提升、展平——但保证改写前后查询结果完全一致,为后续执行层的高效优化铺路。

📌 本文按理解难度递进排列规则编号。源码中 BooleanQuery.rewrite() 实际包含 12 个步骤,本文将其中 SHOULD 去重和 MUST 去重合并为规则 8,并按逻辑将 MatchAll→ConstantScore 编为规则 11,因此源码实际执行顺序按本文编号为:1→2→3→4→5→6→7→8→11→9→10(ConstantScore 转换在展平和 minShouldMatch 对齐之前执行)。


规则 1-3:消除不可能、去重、矛盾检测 #

这三条是防御性规则,含义很容易理解,快速过一遍:

#规则触发条件行为
1空查询消除没有任何子句MatchNoDocsQuery
2单子句拆包只有 1 个子句拆掉 BooleanQuery 外壳,直接用内部查询。SHOULD/MUST 直接返回内部查询;FILTER 包裹为 BoostQuery(ConstantScoreQuery(query), 0)(确保得分为零);MUST_NOT → MatchNoDocsQuery
3递归重写 + MatchNoDocs 短路子句重写后变化,或含 MatchNoDocs递归简化每个子句(FILTER/MUST_NOT 先包裹 ConstantScoreQuery 再重写再剥壳,SHOULD/MUST 直接重写);SHOULD/MUST_NOT 中的 MatchNoDocs 直接移除,MUST/FILTER 中的 MatchNoDocs 导致整体短路
规则 2 示例:
BooleanQuery { MUST: [TermQuery(status:published)] }
       ↓  rewrite
TermQuery(status:published)

BooleanQuery { FILTER: [TermQuery(status:published)] }
       ↓  rewrite
BoostQuery(ConstantScoreQuery(TermQuery(status:published)), 0)

规则 3 示例:
must: [MatchNoDocsQuery], should: [TermQuery(A)]
       ↓  rewrite(MUST 中含 MatchNoDocs → 整体短路)
MatchNoDocsQuery

规则 4-6:去重、矛盾检测、冗余移除 #

继续快速过:

#规则触发条件行为
4FILTER/MUST_NOT 去重相同子句重复出现HashSet 自动去重(基于 Query.equals())。SHOULD/MUST 用 Multiset 保留重复(以便后续规则 8 做 boost 求和)
5矛盾检测MUST 或 FILTER 与 MUST_NOT 含同一子句,或 MUST_NOT 含 MatchAllMatchNoDocsQuery
6冗余 FILTER 移除FILTER 与 MUST 重叠,或 FILTER 含 MatchAllFILTER/MUST 重叠:无条件移除冗余 FILTER;FILTER 含 MatchAll:仅当移除后仍有正向子句时移除(filters.size() > 1 \|\| !mustClauses.isEmpty()
规则 4 示例:
filter: [term:active, term:active, range:age>18] → filter: [term:active, range:age>18]

规则 6 示例:
must: [term:active], filter: [term:active, range:age>18] → must: [term:active], filter: [range:age>18]

规则 7:SHOULD + FILTER → MUST 提升 ⭐ #

触发条件:同一个子查询同时出现在 SHOULD 和 FILTER 子句中。

行为:将该子查询的 SHOULD 子句改为 MUST(原 FILTER 子句直接丢弃,因为 MUST 已隐含了 FILTER 的过滤语义)。源码里会同时下调 minimumNumberShouldMatch(每提升一个子句 minShouldMatch--,循环结束后统一 Math.max(0, minShouldMatch) 确保不低于 0):

  • 若提升后 minShouldMatch == 0,mix 路径走 req+opt(ReqOptSumScorer
  • 若提升后 minShouldMatch > 0,仍走 conjunction-disjunction mix(ConjunctionScorer(req,opt)

也就是说,规则 7 一定会改变查询形态,但是否切到 ReqOptSumScorer 取决于 minShouldMatch 是否归零。

优化前:
┌───────────────────────┐
│ SHOULD: [term:A]      │
│ FILTER: [term:A]      │
│ SHOULD: [term:B]      │
└───────────────────────┘
         ↓  rewrite
优化后:
┌───────────────────────┐
│ MUST:   [term:A]      │  ← 提升为 MUST!
│ SHOULD: [term:B]      │
└───────────────────────┘

💡 类比:一个人同时是"候选人"(SHOULD)又是"已入职"(FILTER)。既然已经入职,直接列入正式编制(MUST)。

⚠️ minShouldMatch 联动:每将一个 SHOULD 提升为 MUST,minimumNumberShouldMatch 相应减 1(循环结束后 Math.max(0, minShouldMatch) 兜底),确保语义等价。例如原有 minimum_should_match: 2 且两个 SHOULD 中有一个被提升,重写后 minShouldMatch 变为 1。


规则 8:SHOULD / MUST 去重(boost 求和) #

触发条件:SHOULD 或 MUST 中出现了相同的子句(解包 BoostQuery 后底层查询相同)。注意:SHOULD 去重仅在 minimumNumberShouldMatch ≤ 1 时触发;若 minShouldMatch > 1,Lucene 不会合并重复的 SHOULD 子句(多个重复出现在高 minShouldMatch 场景下语义不可简单合并)。MUST 去重则没有此限制,无论 minShouldMatch 为何值都会合并重复的 MUST 子句。

行为:合并重复子句,将它们的 boost 相加。FILTER 和 MUST_NOT 的去重由规则 4 处理(直接删除),而 SHOULD 和 MUST 的重复是有意义的——不同的 boost 意味着不同的评分权重,所以求和保留。不合并的话,同一个 term 会创建两套独立的迭代器,都遍历相同的文档列表,浪费翻倍。

should: [term:hello^1.5, term:hello^2.0, term:world]
       ↓  rewrite
should: [term:hello^3.5, term:world]
(两个 hello 的权重合并:1.5 + 2.0 = 3.5)

💡 类比:一个学生选了同一门课两次,一次记 1.5 学分,一次记 2 学分。不需要上两次课,合并为 3.5 学分即可。


规则 9:SHOULD 嵌套展平 ⭐ #

触发条件:一个 bool 查询的 SHOULD 子句里,嵌套了另一个纯 SHOULDbool 查询(即内层没有 MUST、FILTER、MUST_NOT,只有 SHOULD,且 minimum_should_match ≤ 1)。

行为:把内层 SHOULD 子句全部"提升"到外层,展平为同一级别的 SHOULD 子句。展平后 WAND 能看到每个子句的独立 maxScore,估算更紧,剪枝更激进;如果不展平,WAND 只能看到内层查询的总体上界(黑盒),剪枝不够狠。

优化前:
       BoolQuery (外层)
      /                \
   SHOULD            SHOULD
  (term:A)        (内层 BoolQuery)
                     /      \
                 SHOULD    SHOULD
                (term:B)  (term:C)

         ↓  rewrite

优化后:
       BoolQuery
      /    |    \
  SHOULD SHOULD SHOULD
 (term:A)(term:B)(term:C)

实践建议:如果你在 should 里嵌套了多层 bool,且内层全是 SHOULD 子句,EasySearch 会自动展平。但如果内层有 minimum_should_match >= 2,则不会展平(语义不等价),这类情况应尽量手动展平或重构查询结构。

💡 为什么展平能更激进地剪枝?假设内层 bool 有两个子句,maxScore 分别是 8 和 3。展平前,WAND 只看到"这个内层查询最多得 8+3=11 分",不管当前文档匹配了哪些子句,上界永远是 11;展平后,WAND 逐子句检查——某个文档如果不匹配 maxScore=8 的子句,只剩 maxScore=3 的子句可能匹配,上界从 11 降到 3。如果录取线是 5,3 < 5,这个文档不可能入选——直接跳过,不用再算分了。


规则 10:SHOULD 数量与 minimumShouldMatch 的对齐 #

触发条件:SHOULD 子句数量与 minimum_should_match 的大小关系。

行为:分两种情况:

  • SHOULD 数量 < minimumShouldMatch:不可能满足 → 直接返回 MatchNoDocsQuery,省去无用计算
  • SHOULD 数量 == minimumShouldMatch:所有 SHOULD 提升为 MUST,从 WANDScorer(调度开销大)转入 ConjunctionDISI(cost 排序,更高效)
should: [A, B],minimum_should_match: 3
       ↓  rewrite(2 < 3,不可能满足)
MatchNoDocsQuery

should: [A, B, C],minimum_should_match: 3
       ↓  rewrite(3 == 3,等价于全部 MUST)
must: [A, B, C]

💡 类比:开会时,如果"3 个可选发言人必须全部到场"——那"可选"就没意义了,等价于"3 个必须到场"。如果要求"3 人到场但只有 2 人可选"——不可能,直接取消会议。

一个容易忽略的场景:在动态拼接查询时(例如从用户的多个筛选条件生成 should,然后设置 minimum_should_match 等于条件数量),这条规则会自动把它转化为更高效的 MUST 查询,无需手动改写。


规则 11:MatchAll + FILTER → ConstantScoreQuery #

触发条件:BooleanQuery 恰好只有一个 MUST 子句且为 MatchAllDocsQuery,且至少有一个 FILTER 子句。

行为:将所有 FILTER + MUST_NOT 组成内部 BooleanQuery,整体包裹为 ConstantScoreQuery(绕过评分,返回固定分数),作为外层 MUST 加入;SHOULD 子句加回外层(不丢弃);原始 MatchAllDocsQuery 被消耗。MatchAllDocsQuery 在 BooleanQuery 框架里有额外调度开销,ConstantScoreQuery 执行路径更直接。

⚠️ 注意:纯 filter 查询没有 MUST 子句,不满足 musts.size() == 1 的前提,不触发本规则。FILTER 子句直接进入合取路径,由 ConjunctionDISI 按 cost 排序处理。


在 11 条规则中,标 ⭐ 的规则 7(SHOULD+FILTER→MUST)和规则 9(SHOULD 嵌套展平)对执行性能影响最大——前者决定子句能否进入 ConjunctionDISI 的 cost 排序路径,后者决定 WANDScorer 能否做全局剪枝。


五、实战:一条 rewrite 规则如何改变执行路径 #

前面列了 11 条规则,这一节用具体例子展示:构建层的一条 rewrite 规则,如何直接影响执行层的路径选择。

假设你有一个查询:

{
  "bool": {
    "should": [
      { "term": { "status": "published" } },
      { "term": { "category": "ai" } }
    ],
    "filter": [{ "term": { "status": "published" } }]
  }
}

status:published 同时出现在 shouldfilter——规则 7 会把它提升为 MUST,并下调 minShouldMatch。下图假设提升后 minShouldMatch=0,执行路径因此发生根本变化:

┌─────────────────────────────────────────────────────────────────┐
│  没有 rewrite 优化(假设)                                        │
│  minShouldMatch=1,走 conjunction-disjunction mix 路径           │
│                                                                 │
│  ┌────────────────────────────┐                                 │
│  │ ConjunctionScorer          │                                 │
│  │ ├─ FilterScorer            │  published 出现两次:            │
│  │ │  published (score=0)     │  • FILTER 里遍历一遍(只过滤)     │
│  │ └─ DisjunctionSumScorer    │  • SHOULD 里再遍历一遍(评分)     │
│  │    ├─ published            │  = 同一个 term 被两个迭代器        │
│  │    └─ ai                   │    各跑一遍,浪费!               │
│  └────────────────────────────┘                                 │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│  rewrite 优化后(实际)                                           │
│  minShouldMatch=0,走 req+opt 路径                               │
│                                                                 │
│  ┌────────────────────────────┐                                 │
│  │ ReqOptSumScorer            │  published 只出现一次:           │
│  │ ├─ req: published (有评分)  │  • 作为 MUST,一次迭代同时        │
│  │ └─ opt: ai (可选加分)       │    完成过滤和评分                 │
│  └────────────────────────────┘                                 │
└─────────────────────────────────────────────────────────────────┘

优化前,status:published 被两个迭代器各遍历一遍;优化后,一次迭代同时完成过滤和评分——一条 rewrite 规则,改变了执行路径的选择。它不做代价排序,但决定了哪些子句有资格进入更高效的路径。


六、动手验证:用 Profile API 观察 rewrite 效果 #

理论再多,不如自己跑一遍。Easysearch 的 Profile API 可以直接暴露 rewrite 后的查询形态,不需要读源码,几秒钟就能验证。

6.1 验证规则 7:SHOULD + FILTER → MUST 提升 #

准备好一个含有 statuscategory 字段的索引,执行:

GET /products/_search
{
  "profile": true,
  "query": {
    "bool": {
      "should": [
        { "term": { "status": "published" }},
        { "term": { "category": "ai" }}
      ],
      "filter": [
        { "term": { "status": "published" }}
      ]
    }
  }
}

找到响应中 profile.shards[0].searches[0].query[0].description 字段(具体格式可能因版本略有不同):

  • 你写的:SHOULD + FILTER 并存(两个地方都有 status:published
  • 实际执行+status:published category:ai

注意 + 前缀——在 Lucene 的查询 description 语法中,+ 表示 MUST,没有符号表示 SHOULD。status:published 前面有 +,说明 rewrite 已经把它提升为 MUST,查询形态已经发生了变化。

6.2 验证规则 10:SHOULD 数量 == minimumShouldMatch → 全部提升为 MUST #

GET /products/_search
{
  "profile": true,
  "query": {
    "bool": {
      "should": [
        { "term": { "status": "published" }},
        { "term": { "category": "ai" }}
      ],
      "minimum_should_match": 2
    }
  }
}

profile 的 description 应该显示 +status:published +category:ai——两个 term 都带 + 前缀,说明全部提升为 MUST,这个查询实际上会走第二篇要讲的 ConjunctionDISI 路径,而非 WANDScorer。

6.3 理解 Profile 响应的结构 #

一个完整的 Profile 响应包含大量信息,但读懂核心字段只需关注三个位置:

{
  "profile": {
    "shards": [{
      "searches": [{
        "query": [{
          "type": "BooleanQuery",
          "description": "+status:published +category:ai",
          "breakdown": {
            "next_doc": 12750,      "next_doc_count": 1,
            "advance":  0,          "advance_count":  0,
            "create_weight": 375375, "create_weight_count": 1,
            "build_scorer":  248958, "build_scorer_count":  2
          },
          "children": [
            { "type": "TermQuery", "description": "status:published", ... },
            { "type": "TermQuery", "description": "category:ai", ... }
          ]
        }],
        "rewrite_time": 146958
      }]
    }]
  }
}

快速解读三个关键位置:

字段含义怎么看
descriptionrewrite 后的查询形态+ 表示 MUST,无前缀表示 SHOULD,- 表示 MUST_NOT
advance / advance_count迭代器跳转的耗时 / 次数第二篇核心指标。count 越小 = 跳转越少 = cost 排序效果越好
rewrite_timerewrite 阶段的总耗时本文 11 条规则的总执行时间,通常很小(微秒级)

💡 小技巧:breakdown 里每个指标都有两个 key——xxx 是耗时(纳秒),xxx_count 是调用次数。想看"做了多少次"看 _count,想看"花了多少时间"看不带 _count 的。


七、小结与预告 #

我们走完了布尔查询在执行前的两个构建层:

Easysearch 层做的是合法化处理——保持子句顺序,修补极端情况(纯否定、空查询、MatchNone 短路),设置 minShouldMatch。它不会改变你查询的"形状"。

Lucene rewrite 层通过 11 条逻辑等价改写规则改变查询的"形态":

  • 规则 1-6 是防御性规则,消除空查询、冗余和矛盾
  • 规则 7 和规则 10 是提升性规则,把更多子句导入 ConjunctionDISI 的合取路径,为 cost 排序创造更大的发挥空间
  • 规则 9 是为析取优化准备的,展平 SHOULD 嵌套让 WANDScorer 能做全局剪枝
  • 规则 8 是评分优化(合并重复 boost),规则 11 绕过不必要的评分计算

这两层都不做代价排序,但它们决定了哪些子句有资格进入更高效的执行路径。


下一篇预告

当 MUST 子句进入 Scorer 构造层,Lucene 会创建 ConjunctionDISI,对所有迭代器按 cost() 升序排序——最稀疏的放在第一位,承担"领头"角色,最大限度地用跳转(advance())跳过不满足条件的文档。

匹配文档最少的迭代器,为什么反而被选来驱动整个遍历?——它产生的候选集最小,所有迭代器的验证次数因此被压到最低。这个看似"以弱领强"的设计,正是合取查询性能优化的核心。我们在第二篇,通过源码、图解和 Profile API 实测,把这个机制讲透。

标签
Easysearch x
布尔查询 x
BoolQuery x
排序 x
自主可控 x
超聚变 x
FusionOS x
信创 x
CocoAI x
Elasticsearch x
中国银行 x
搜索引擎 x
DTCC x
中国数据库技术大会 x
爱加密 x
安全 x
极限网关 x
PICC x
Gateway x
Coco AI x
信创产品评估证书 x
达梦数据库 x
CDC x
AI搜索 x
DBX x
客户端 x
可视化 x
数据库 x
达梦 x
兼容认证 x
产品更新 x
巡检 x
CCR x
语义搜索 x
向量检索 x
RAG x
knn x
2026 x
信通院 x
TDBC x
可信数据库大会 x
中国数据库产业图谱 x
ZSTD x
Bboss x
开源 x
国产化 x
Java 客户端 x
Console x
搜索平台 x
鲲鹏 x
统信UOS x
DBackup x
鼎甲数据 x
备份与恢复 x
Coco x
迁移 x
快照 x
snapshot x
向量 x
IK x
分词 x
performance x
插件 x
开发 x
自定义 x
扩展 x
AI x
幻觉 x
大模型 x
Agent x
Mem0 x
MCP x
AI Agent x
kNN x
规则引擎 x
银行 x
保险 x
风控 x
Rules x
Percolator x
国产 x
搜索 x
Lucene x
GraalVM x
JDK x
赞助 x
开源生态 x
社区 x
二等奖 x
兴智杯 x
人工智能 x
赛事 x
低空经济 x
商业化 x
数据分析 x
金猿奖 x
技术卓越奖 x
创新产品奖 x
IT168 x
APM x
Skywalking x
Easy-Es x
GitLab x
代码审核 x
石油石化 x
Gitee x
投票 x
Meilisearch x
Rust x
轻量级 x
搜索百科 x
Docker x
Docker Compose x
Easyserach x
DevOps x
国产替代 x
backup x
esdump x
source_reuse x
ignore_above x
OpenSearch x
AWS x
Solr x
Easyearch x
发明专利 x
数据分区 x
国际专利 x
一等奖 x
人工智能应用创新大赛 x
bulk x
embedding x
OpenAI x
2025 x
搜索型数据库 x
上海开源创新菁英荟 x
开源创新新星企业 x
Workshop x
AI 搜索 x
智能助手 x
Automation x
Logstash x
MongoDB x
开源中国 x
直播 x
merge x
Elasticsearch 9 x
GitCode x
Cloud x
rollup x
Kubernetes x
Operator x
Arm64 x
Snapshot x
S3 x
Grafana x
Opensearch x
Nginx x
直播活动 x
搜索客社区 x
Meetup x
ES x
企业搜索 x
DeepSeek x
certificate x
windows x
Rollup x
TopN x
Filebeat x
Ubuntu x
请求限速 x
INFINI Console x
指标 x
Kibana x
多集群 x
client x
Spring Boot x
ECE x
ES Bulk x
vector database x
Postgres x
可搜索快照 x
SDK x
官网 x
Web 开发 x
Next.js x
React x
Three.js x
Metrics x
Helm x
filter x
querycache x
practice x
localStorage x
响应式 x
时间组件 x
时区组件 x
极限科技 x
三周年 x
周年庆 x
国家高新技术企业 x
校园招聘 x
湖北工业大学 x
Tauri x
Web 开发人员 x
桌面应用开发 x
桌面端 x
Electron x
Pizza x
认证培训 x
报名 x
Scrapy x
爬虫 x
Rust开发者大会 x
docsearch x
文档搜索 x
Easyseach x
有奖征文 x
黑神话悟空 x
EKS x
征文系列 x
跨集群搜索 x
科技中小企业 x
白皮书 x
Python SDK x
数据库产业图谱 x
超大规模 x
分布式集群 x
写入限流 x
2024可信数据库发展大会 x
创新型中小企业 x
搜索数据库 x
正排索引 x
免费许可证 x
K8S x
DTC2024 x
实时搜索 x
ES国产化 x
Redis x
OOM x
测试 x
内存 x
趋势 x
AI绘画 x
Stable Diffusion x
Diffusion x
Model x
GAN x
知识图 x
向量数据库 x
中国信通院 x
星河(Galaxy) x
标杆案例 x
鲲鹏技术认证 x
日志平台 x
LDAP x
Loadgen x
中国一汽 x
国内数据库 x
墨天轮 x
监控系统 x
集成测试 x
Helm Charts x
国产适配 x
兆芯 x
Linux x
LoongArch x
信创适配 x
二维拆分算法 x
中国移动云 x
Vault x
加密 x
安全工具 x
图片搜索 x
Alerting x
SQL x
Embedding x
可信数据库 x
统信 x
海光 x
龙芯 x
restore x
Arm x
大数据企业证书 x
移动云大会 x
信通院产品评测 x
国内首家 x
数据可视化 x
北京软协 x
第十届理事会会员单位 x
Apache Arrow x
宣传片 x
大会分享 x
多集群管理 x
无缝数据迁移 x
Loadrun x
INFINI Gateway x
log4j x