快速入门:按租户或知识库检索

更新时间:
复制 MD 格式

本例用一个 Collection(统一定义字段的数据集合)管理两个租户,无需为每个租户单独维护索引。租户分别对应 tenant-a 和 tenant-b 两个 Slice(业务数据分区),写入和查询时通过 _slice 指定租户。这种按业务标识选择数据范围的方式称为命名空间模式(exact),也是默认模式。

完成首次检索只需创建 Collection → 写入数据 → 等待数据可搜索并查询。下文将预创建 Backing、提前注册 Slice 和缓存预热标为可选;批量开通租户前推荐先预创建 Backing 并注册 Slice,对首次查询延迟敏感时推荐先预热。

准备实例

需要一个可用的 Agent 引擎版实例。尚未创建时,先完成创建和连接实例。后续请求在 Kibana Dev Tools 中执行,操作账号需要 Collection 管理和数据读写权限,见 Collection 权限。

应用通过 Collection 名和业务 Slice 名访问数据。Slice 用于限定数据范围,不是账号权限边界;租户身份校验和访问授权仍需由应用完成。

步骤一:创建 Collection

创建 knowledge-chunks,统一定义租户标识、标题、正文和向量等字段。示例向量可直接用于试用;接入真实业务时,向量维度和相似度应与模型一致。

PUT /_slice_collection/knowledge-chunks
{
  "max_slices_per_shard": 200,
  "settings": {
    "index.number_of_shards": 2,
    "index.number_of_replicas": 2
  },
  "mappings": {
    "properties": {
      "tenant_id": { "type": "keyword" },
      "document_id": { "type": "keyword" },
      "title": { "type": "text" },
      "content": { "type": "text" },
      "category": { "type": "keyword" },
      "updated_at": { "type": "date" },
      "embedding": {
        "type": "dense_vector",
        "dims": 4,
        "index": true,
        "similarity": "cosine",
        "index_options": {
          "type": "bbq_disk"
        }
      }
    }
  }
}

确认返回 acknowledged: true,表示 Collection 配置已创建。

系统将文档存放在 Backing(底层索引)中,一个 Backing 可以承载多个 Slice。max_slices_per_shard 用于控制每个 Backing 接收新 Slice 的数量;调小它会让新 Slice 更早使用其他 Backing。它不限制单个 Slice 的文档数,容量计算见容量参数如何生效。

预创建 Backing(可选,推荐)

首次试用可以跳过,系统会按需创建。批量开通租户或导入数据前,推荐先准备 5 个 Backing,减少首次写入时创建索引的等待,让新租户的数据分散到多个底层索引上,有助于分散读写负载:

PUT /_slice_collection/knowledge-chunks/backings?count=5

确认返回 acknowledged: true,且 backings 中有 5 个名称。重复执行会检查并补齐同一批索引;已有数据不会因此重新分布。生产环境应结合数据量和分片资源调整数量,参数及分配规则见预创建 Backing。

提前注册 Slice(可选)

默认允许首次写入时自动注册 Slice。在租户开通时提前准备业务分区,可减少首次业务写入时的注册等待:

PUT /_slice_collection/knowledge-chunks/slices
{
  "slices": ["tenant-a", "tenant-b"]
}

确认顶层 errors 为 false,每个 items[].result 为 created 或 noop。created 表示新注册,noop 表示该 Slice 已存在且无需更改;某项为 failed 时,先处理其错误再写入。

步骤二:写入数据

常规写入不应传 refresh,也不要在应用代码中调用 _refresh。 这类操作可能显著增加数据发布、对象存储读取和查询节点刷新开销。仅在低频同步点确需使用 refresh=wait_for 时,先核对适用条件与代价。

批量写入

使用一次 Bulk 请求,向两个租户各写入两条文档。两个租户使用相同的 _id,但文档内容不同,用于验证:_id 只需在同一个 Slice 内唯一,不同 Slice 的同 ID 文档不会相互覆盖。

POST /_bulk
{ "index": { "_index": "knowledge-chunks", "_id": "chunk-1001", "_slice": "tenant-a" } }
{ "tenant_id": "tenant-a", "document_id": "doc-refund-policy", "title": "退款与退货政策", "content": "重复购买的商品可以在订单完成后的七天内申请退款。", "category": "after-sales", "updated_at": "2026-07-30T10:00:00Z", "embedding": [0.82, 0.10, 0.05, 0.03] }
{ "index": { "_index": "knowledge-chunks", "_id": "chunk-1001", "_slice": "tenant-b" } }
{ "tenant_id": "tenant-b", "document_id": "doc-shipping-status", "title": "查询物流状态", "content": "在订单详情页打开物流信息,即可查看最新配送状态。", "category": "shipping", "updated_at": "2026-07-30T10:01:00Z", "embedding": [0.12, 0.78, 0.06, 0.04] }
{ "index": { "_index": "knowledge-chunks", "_id": "chunk-1002", "_slice": "tenant-a" } }
{ "tenant_id": "tenant-a", "document_id": "doc-change-address", "title": "修改收货地址", "content": "订单发货前,可以在订单详情页修改收货地址。", "category": "orders", "updated_at": "2026-07-30T10:02:00Z", "embedding": [0.75, 0.16, 0.06, 0.03] }
{ "index": { "_index": "knowledge-chunks", "_id": "chunk-1002", "_slice": "tenant-b" } }
{ "tenant_id": "tenant-b", "document_id": "doc-invoice", "title": "申请电子发票", "content": "订单完成后,可以在发票管理页面申请电子发票。", "category": "billing", "updated_at": "2026-07-30T10:03:00Z", "embedding": [0.18, 0.70, 0.08, 0.04] }

Bulk 使用 NDJSON 格式,每条操作和文档各占一行,末尾保留换行。确认响应顶层 errors 为 false;出现部分失败时,逐项检查 items 中的错误,处理后再继续。

写入响应中的 _index 可能是 .sc-* 底层索引名;读取或查询响应中的 _routing 可能是系统生成的 Slice 内部标识(slice_uid),与传入的业务 Slice 名不同。这是正常现象。后续请求仍使用 knowledge-chunks 和 tenant-a 等业务名称,不要把这些内部值当作 Collection 名或 _slice 参数,也不要解析其格式。

按 ID 验证写入(可选)

GET 默认实时读取,正常情况下无需等待搜索刷新。分别读取两个租户的 chunk-1001:

GET /knowledge-chunks/_doc/chunk-1001?_slice=tenant-a
GET /knowledge-chunks/_doc/chunk-1001?_slice=tenant-b

两次响应的 found 应均为 true,标题分别为“退款与退货政策”和“查询物流状态”,说明同 ID 文档分别保存在两个 Slice 中。主分片不可用时的读取边界见按 ID 确认写入。

步骤三:查询租户内的数据

写入成功后,等待约 5 秒,让后台自动刷新使数据可搜索,再执行预热或查询。若结果尚未包含新数据,再等一个自动刷新周期后重试;实际可搜索时间还受负载影响,5 秒不是完成时限。

预热待查询的 Slice(可选,推荐)

预热可减少首次查询从对象存储加载冷数据的等待。接下来查询 tenant-a,可以先将它的可搜索数据加载到查询节点缓存,让后续查询复用。此处同步等待,便于观察结果:

POST /knowledge-chunks/_warm_slice?_slice=tenant-a&wait_for_completion=true&timeout=60s

确认请求成功且 _shards.failed 为 0。本例已写入数据;若 _shards.total=0,先确认查询分片可用,并用实际查询确认数据已可搜索,再按需重试预热。超时或分片失败时,检查错误后再重试。预热只覆盖当时已可搜索的数据,不包含之后的新数据。

生产环境推荐在用户选中知识库等可预测的访问时机提前异步预热,并控制并发;后续查询复用缓存,无需每条查询都等待预热。异步返回 ACCEPTED 只表示已提交,结果判断见预热 Slice 缓存。

后续步骤