Skip to content

Commit bc43d94

Browse files
committed
blog: add index
1 parent 65ee6c0 commit bc43d94

1 file changed

Lines changed: 181 additions & 0 deletions

File tree

content/zh/blog/Index/index.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
title: "使用 Index 快速查询配置数据"
3+
description: "介绍 Tableau 的 Index 功能,实现对配置表的高效索引查询。"
4+
lead: "介绍 Tableau 的 Index 功能,实现对配置表的高效索引查询。"
5+
date: 2026-03-30T15:00:00+08:00
6+
lastmod: 2026-03-30T15:00:00+08:00
7+
draft: false
8+
contributors: ["Wenchy"]
9+
---
10+
11+
## 背景
12+
13+
在游戏或业务配置中,我们经常需要根据**非主键字段**快速查找数据。例如:
14+
15+
- 查找所有 `Type == 1` 的商店
16+
- 查找某个道具下所有 `PropID == 2` 的属性
17+
18+
如果每次都遍历整张表,性能开销较大。Tableau 提供了 **Index** metasheet 选项,让 loader 插件在加载时自动构建索引,实现 O(1) 的快速查询。
19+
20+
---
21+
22+
## Index
23+
24+
### 配置方式
25+
26+
`@TABLEAU` metasheet 中,通过 `Index` 列为指定 sheet 设置索引列。
27+
28+
**格式:**
29+
30+
- 单列 Index:`Column@IndexName`
31+
- 多列 Index(Composite Index):`(Column1,Column2)@IndexName`
32+
- 多个 Index 用逗号分隔:`Type@ThemeShop, (ID,Type)@SpecialShop`
33+
34+
> **注意**:被索引的列必须是同一 struct(message)内的 scalar 或 enum 字段。
35+
36+
### 示例
37+
38+
*HelloWorld.xlsx* 中的 `List` sheet(list 布局)以及 `@TABLEAU` metasheet 配置:
39+
40+
{{< spreadsheet "HelloWorld.xlsx" List "@TABLEAU" >}}
41+
42+
{{< sheet colored >}}
43+
44+
| ID | Type | Desc |
45+
| ----------- | ----------- | ------------- |
46+
| [Shop]int32 | int32 | string |
47+
| Shop's ID | Shop's type | Shop's desc |
48+
| 1 | 1 | Shoes shop. |
49+
| 2 | 1 | T-Shirt shop. |
50+
| 3 | 2 | Fruite shop. |
51+
52+
{{< /sheet >}}
53+
54+
{{< sheet colored1 >}}
55+
56+
| Sheet | Index |
57+
| ----- | ---------------------------------------------- |
58+
| List | ID@Shop, Type@ThemeShop, (ID,Type)@SpecialShop |
59+
60+
{{< /sheet >}}
61+
62+
{{< /spreadsheet >}}
63+
64+
这样会生成三个索引:
65+
66+
| Index 名 | 索引键 | 说明 |
67+
| ------------- | ----------- | ------------------- |
68+
| `Shop` | `ID` | 按 ID 查找商店 |
69+
| `ThemeShop` | `Type` | 按类型查找商店列表 |
70+
| `SpecialShop` | `(ID,Type)` | 按 ID+Type 组合查找 |
71+
72+
### 生成的 API(Go 示例)
73+
74+
```go
75+
// 获取完整索引 map
76+
indexMap := conf.FindThemeShopMap()
77+
78+
// 按 Type 查找所有匹配的商店(返回 slice)
79+
shops := conf.FindThemeShop(1)
80+
81+
// 按 Type 查找第一个匹配的商店
82+
shop := conf.FindFirstThemeShop(1)
83+
```
84+
85+
对于嵌套在上层 map 中的 struct,还会生成带作用域的查询 API:
86+
87+
```go
88+
// 在指定上层 map key 范围内查找
89+
shops := conf.FindThemeShop1(itemID, shopType)
90+
```
91+
92+
---
93+
94+
## 复杂嵌套示例:map → list → map → list
95+
96+
当索引目标深埋在多层嵌套结构中时,Tableau 会为每一层上级 map 自动生成**带作用域的查询 API**,方便在指定范围内精确查找。
97+
98+
### 数据结构
99+
100+
`ChapterConf` sheet 为例,结构为:
101+
102+
```bash
103+
ChapterConf
104+
└── map<uint32, Chapter> # 第1层:章 map(key: ChapterID)
105+
└── [Section]uint32 # 第2层:节 list(key: SectionID)
106+
└── map<int32, Prop> # 第3层:属性 map(key: PropID)
107+
└── [Tag]int32 # 第4层:标签 list(key: TagID)
108+
├── TagID
109+
└── Type ← 对此字段建立 Index
110+
```
111+
112+
### 配置示例
113+
114+
{{< spreadsheet "HelloWorld.xlsx" ChapterConf "@TABLEAU" >}}
115+
116+
{{< sheet colored >}}
117+
118+
| ChapterID | SectionID | PropID | TagID | Type |
119+
| -------------------- | --------------- | ---------------- | ---------- | ---------- |
120+
| map<uint32, Chapter> | [Section]uint32 | map<int32, Prop> | [Tag]int32 | int32 |
121+
| Chapter's ID | Section's ID | Prop's ID | Tag's ID | Tag's type |
122+
| 1 | 1 | 1 | 1 | 10 |
123+
| 1 | 1 | 1 | 2 | 20 |
124+
| 1 | 1 | 2 | 3 | 10 |
125+
| 1 | 2 | 1 | 4 | 30 |
126+
| 2 | 1 | 1 | 5 | 10 |
127+
128+
{{< /sheet >}}
129+
130+
{{< sheet colored1 >}}
131+
132+
| Sheet | Index |
133+
| ----------- | -------------- |
134+
| ChapterConf | Type@TagByType |
135+
136+
{{< /sheet >}}
137+
138+
{{< /spreadsheet >}}
139+
140+
`Type@TagByType` 表示:对 `Tag` struct 中的 `Type` 字段建立名为 `TagByType` 的索引。
141+
142+
### 生成的 API(Go 示例)
143+
144+
由于 `Tag` 嵌套在 **2 层上级 map**`Chapter` map 和 `Prop` map)中,Tableau 会生成全局查询 API 以及带作用域的 API:
145+
146+
```go
147+
// 全局查询:跨所有章节和属性,按 Type 查找所有 Tag
148+
tags := conf.FindTagByType(10)
149+
150+
// 按 Type 查找第一个 Tag(全局)
151+
tag := conf.FindFirstTagByType(10)
152+
153+
// 带作用域查询(1 层上级 map:Prop map)
154+
// 在指定 ChapterID + SectionID + PropID 范围内,按 Type 查找
155+
tags1 := conf.FindTagByType1(chapterID, sectionID, propID, 10)
156+
157+
// 带作用域查询(2 层上级 map:Chapter map)
158+
// 在指定 ChapterID 范围内,按 Type 查找
159+
tags2 := conf.FindTagByType2(chapterID, 10)
160+
```
161+
162+
> **说明**`FindTagByTypeN` 中的 `N` 表示从最近的上级 map 往上数第 N 层。`N=1` 为直接父级 map(`Prop` map),`N=2` 为祖父级 map(`Chapter` map)。
163+
164+
---
165+
166+
## 支持的列类型
167+
168+
Index 和 OrderedIndex 均支持以下列类型:
169+
170+
- **scalar**:数值、布尔值、字符串、bytes
171+
- **enum**:如 `enum<.FruitType>`
172+
- **incell scalar list**:如 `[]int32`
173+
- **incell enum list**:如 `[]enum<.FruitType>`
174+
175+
---
176+
177+
## 参考文档
178+
179+
- [Metasheet 选项:Index](../../docs/excel/metasheet/#选项-index)
180+
181+
- [Go Loader API: OrderedIndex](../../docs/api/loader/go/#orderedindex)

0 commit comments

Comments
 (0)