imean-cassandra-orm 1.5.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -280
- package/dist/mod.cjs +643 -422
- package/dist/mod.d.cts +169 -250
- package/dist/mod.d.ts +169 -250
- package/dist/mod.js +641 -418
- package/package.json +63 -63
package/README.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
# Cassandra ORM
|
|
1
|
+
# IMean Cassandra ORM
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
一个基于 Zod 的 Cassandra ORM,提供类型安全的 schema 定义和数据库操作。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- 🎯 **类型安全**: 基于 Zod 的 schema 验证和 TypeScript 类型推断,确保入库和出库的数据类型安全。
|
|
8
|
+
- 🔧 **自动 CQL 生成**: 自动生成 Cassandra CQL 语句,无需手写。
|
|
9
|
+
- 📊 **完整 CRUD**: 支持插入、查询、更新、删除操作。
|
|
10
|
+
- 🚀 **批量操作**: 支持批量插入,提升性能。
|
|
11
|
+
- 🎨 **简洁 API**: 简单易用的 API 设计,通过 Client 统一管理模型。
|
|
12
|
+
- 🔄 **Schema 同步**: 自动创建和同步 keyspace 和表结构。
|
|
13
|
+
- ⚙️ **Keyspace 配置**: 支持自定义复制策略和配置。
|
|
14
|
+
- 🤖 **自动序列化**: 自动处理复杂类型(如 JSON 对象、数组)的序列化和反序列化。
|
|
4
15
|
|
|
5
16
|
## 安装
|
|
6
17
|
|
|
@@ -8,341 +19,240 @@
|
|
|
8
19
|
npm install imean-cassandra-orm
|
|
9
20
|
```
|
|
10
21
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
import { Client as CassandraClient, auth } from "cassandra-driver";
|
|
15
|
-
import { Client, Field, uuid, type Infer } from "imean-cassandra-orm";
|
|
22
|
+
## 快速开始
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
const cassandraClient = new CassandraClient({
|
|
19
|
-
contactPoints: ["localhost"],
|
|
20
|
-
localDataCenter: "datacenter1",
|
|
21
|
-
authProvider: new auth.PlainTextAuthProvider("cassandra", "cassandra"),
|
|
22
|
-
});
|
|
24
|
+
### 1. 定义 Schema
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
const client = new Client(cassandraClient);
|
|
26
|
+
使用 `TableSchema` 和 `zod` 来定义你的表结构。ORM 会根据你的定义自动推断类型和生成数据库表。
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
```typescript
|
|
29
|
+
import { z } from "zod";
|
|
30
|
+
import { TableSchema } from "imean-cassandra-orm";
|
|
31
|
+
|
|
32
|
+
// 定义用户表 schema
|
|
33
|
+
const userSchema = new TableSchema({
|
|
34
|
+
fields: {
|
|
35
|
+
user_id: z.string(),
|
|
36
|
+
email: z.string().email(),
|
|
37
|
+
name: z.string(),
|
|
38
|
+
age: z.number().int().positive(),
|
|
39
|
+
is_active: z.boolean(),
|
|
40
|
+
metadata: z.record(z.any()), // 可以是任意复杂的对象
|
|
41
|
+
created_at: z.date(),
|
|
42
|
+
},
|
|
43
|
+
partitionKey: ["user_id"],
|
|
44
|
+
tableName: "users",
|
|
45
|
+
keyspace: "my_app_keyspace",
|
|
31
46
|
});
|
|
32
47
|
|
|
33
|
-
//
|
|
34
|
-
const
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
// 定义帖子表 schema(带聚类键)
|
|
49
|
+
const postSchema = new TableSchema({
|
|
50
|
+
fields: {
|
|
51
|
+
user_id: z.string(),
|
|
52
|
+
post_id: z.string(),
|
|
53
|
+
title: z.string(),
|
|
54
|
+
content: z.string(),
|
|
55
|
+
tags: z.array(z.string()), // 数组类型
|
|
56
|
+
published_at: z.date(),
|
|
40
57
|
},
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
partitionKey: ["user_id"],
|
|
59
|
+
clusteringKey: { post_id: "desc" }, // 按 post_id 降序
|
|
60
|
+
tableName: "posts",
|
|
61
|
+
keyspace: "my_app_keyspace",
|
|
62
|
+
});
|
|
63
|
+
```
|
|
44
64
|
|
|
45
|
-
|
|
46
|
-
const postModel = client.createModel(
|
|
47
|
-
{
|
|
48
|
-
id: Field.uuid().partitionKey(), // 分区键,必填
|
|
49
|
-
title: Field.text(), // 普通字段,必填
|
|
50
|
-
content: Field.text(), // 普通字段,必填
|
|
51
|
-
created_at: Field.timestamp(), // 普通字段,必填
|
|
52
|
-
},
|
|
53
|
-
"posts"
|
|
54
|
-
);
|
|
65
|
+
### 2. 创建 Client 和模型
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
await client.syncAllSchemas();
|
|
67
|
+
`Client` 是所有操作的入口。你需要先创建一个 `Client` 实例,然后用它来创建 `Model` 实例。
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
id: uuid(), // 必须提供分区键
|
|
62
|
-
name: "张三", // 必须提供聚类键
|
|
63
|
-
age: 25, // 可选
|
|
64
|
-
email: "zhangsan@example.com" // 必填
|
|
65
|
-
});
|
|
69
|
+
```typescript
|
|
70
|
+
import { Client } from "imean-cassandra-orm";
|
|
66
71
|
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
content: "内容",
|
|
72
|
-
created_at: new Date(),
|
|
72
|
+
// 1. 创建 Client 实例
|
|
73
|
+
const client = new Client({
|
|
74
|
+
contactPoints: ["localhost"],
|
|
75
|
+
localDataCenter: "datacenter1",
|
|
73
76
|
});
|
|
74
77
|
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
console.log(foundUser);
|
|
78
|
+
// 2. 连接到 Cassandra
|
|
79
|
+
await client.connect();
|
|
78
80
|
|
|
79
|
-
//
|
|
80
|
-
await client.
|
|
81
|
-
```
|
|
81
|
+
// 3. (可选) 删除旧的 keyspace 以进行全新测试
|
|
82
|
+
await client.dropKeyspace("my_app_keyspace");
|
|
82
83
|
|
|
83
|
-
|
|
84
|
+
// 4. 通过 Client 创建模型实例
|
|
85
|
+
const userModel = client.createModel(userSchema);
|
|
86
|
+
const postModel = client.createModel(postSchema);
|
|
84
87
|
|
|
85
|
-
|
|
88
|
+
// 5. 同步所有模型的 Schema
|
|
89
|
+
// 这会确保 keyspace 和所有相关的表都已创建
|
|
90
|
+
await client.syncSchema();
|
|
91
|
+
```
|
|
86
92
|
|
|
87
|
-
|
|
93
|
+
`client.syncSchema()` 会自动处理所有已创建模型的 schema 同步,你不再需要为每个模型单独调用 `syncSchema()`。
|
|
88
94
|
|
|
89
|
-
|
|
95
|
+
### 3. 基本操作
|
|
90
96
|
|
|
91
|
-
|
|
97
|
+
模型实例提供了完整的 CRUD API。
|
|
92
98
|
|
|
93
99
|
```typescript
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
// 插入数据 (自动序列化 metadata 对象)
|
|
101
|
+
const userData = {
|
|
102
|
+
user_id: "user1",
|
|
103
|
+
email: "user1@example.com",
|
|
104
|
+
name: "张三",
|
|
105
|
+
age: 25,
|
|
106
|
+
is_active: true,
|
|
107
|
+
metadata: { score: 95.5, level: 3, tags: ["vip"] },
|
|
108
|
+
created_at: new Date(),
|
|
109
|
+
};
|
|
110
|
+
await userModel.insert(userData);
|
|
104
111
|
|
|
105
|
-
|
|
112
|
+
// 查询数据 (自动反序列化 metadata)
|
|
113
|
+
const foundUser = await userModel.findOne({ user_id: "user1" });
|
|
114
|
+
console.log(foundUser?.metadata); // { score: 95.5, level: 3, tags: ["vip"] }
|
|
106
115
|
|
|
107
|
-
|
|
116
|
+
// 更新数据
|
|
117
|
+
await userModel.update(
|
|
118
|
+
{ user_id: "user1" },
|
|
119
|
+
{ name: "李四", age: 26 }
|
|
120
|
+
);
|
|
108
121
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
// 推导结果: { id: string }
|
|
122
|
+
// 删除数据
|
|
123
|
+
await userModel.delete({ user_id: "user1" });
|
|
112
124
|
```
|
|
113
125
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
推导聚类键字段类型。
|
|
126
|
+
### 4. 批量操作
|
|
117
127
|
|
|
118
128
|
```typescript
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
// 批量插入
|
|
130
|
+
const usersData = [
|
|
131
|
+
{
|
|
132
|
+
user_id: "user2",
|
|
133
|
+
email: "user2@example.com",
|
|
134
|
+
name: "王五",
|
|
135
|
+
age: 30,
|
|
136
|
+
is_active: true,
|
|
137
|
+
metadata: { score: 88.0 },
|
|
138
|
+
created_at: new Date(),
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
user_id: "user3",
|
|
142
|
+
email: "user3@example.com",
|
|
143
|
+
name: "赵六",
|
|
144
|
+
age: 28,
|
|
145
|
+
is_active: false,
|
|
146
|
+
metadata: { score: 79.2 },
|
|
147
|
+
created_at: new Date(),
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
await userModel.batchInsert(usersData);
|
|
121
151
|
```
|
|
122
152
|
|
|
123
|
-
|
|
153
|
+
### 5. 使用聚类键
|
|
124
154
|
|
|
125
|
-
|
|
155
|
+
当你的 schema 定义了 `clusteringKey` 时,你可以在查询、更新和删除操作中指定它。
|
|
126
156
|
|
|
127
157
|
```typescript
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
158
|
+
// 插入带聚类键的数据
|
|
159
|
+
const postData = {
|
|
160
|
+
user_id: "user1",
|
|
161
|
+
post_id: "post1",
|
|
162
|
+
title: "我的第一篇帖子",
|
|
163
|
+
content: "这是内容...",
|
|
164
|
+
tags: ["技术", "编程"],
|
|
165
|
+
published_at: new Date(),
|
|
132
166
|
};
|
|
167
|
+
await postModel.insert(postData);
|
|
168
|
+
|
|
169
|
+
// 查询特定帖子
|
|
170
|
+
const post = await postModel.findOne(
|
|
171
|
+
{ user_id: "user1" },
|
|
172
|
+
{ post_id: "post1" } // 指定聚类键
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
// 更新特定帖子
|
|
176
|
+
await postModel.update(
|
|
177
|
+
{ user_id: "user1" },
|
|
178
|
+
{ title: "更新后的标题" },
|
|
179
|
+
{ post_id: "post1" } // 指定聚类键
|
|
180
|
+
);
|
|
133
181
|
|
|
134
|
-
|
|
135
|
-
|
|
182
|
+
// 删除特定帖子
|
|
183
|
+
await postModel.delete(
|
|
184
|
+
{ user_id: "user1" },
|
|
185
|
+
{ post_id: "post1" } // 指定聚类键
|
|
186
|
+
);
|
|
136
187
|
```
|
|
137
188
|
|
|
138
|
-
|
|
189
|
+
### 6. 类型安全与校验
|
|
139
190
|
|
|
140
|
-
|
|
191
|
+
ORM 会在数据返回时使用 Zod schema 进行校验,确保你得到的数据是类型安全的。
|
|
141
192
|
|
|
142
193
|
```typescript
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
//
|
|
194
|
+
// 从数据库返回的数据
|
|
195
|
+
const userFromDb = await userModel.findOne({ user_id: "user1" });
|
|
196
|
+
|
|
197
|
+
// userFromDb 的类型是根据 userSchema 推断出来的,具有完整的类型提示
|
|
198
|
+
if (userFromDb) {
|
|
199
|
+
console.log(userFromDb.name.toUpperCase());
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 如果数据库中的数据不符合 schema(例如,手动修改了数据库),
|
|
203
|
+
// 在查询时会抛出 ZodError,防止脏数据进入你的应用。
|
|
152
204
|
```
|
|
153
205
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
3. 可以节省存储空间
|
|
158
|
-
4. 提高查询效率
|
|
206
|
+
## API 参考
|
|
207
|
+
|
|
208
|
+
### `Client`
|
|
159
209
|
|
|
160
|
-
|
|
210
|
+
#### `new Client(options: cassandra.ClientOptions)`
|
|
161
211
|
|
|
162
|
-
|
|
163
|
-
2. 在服务层进行类型检查
|
|
164
|
-
3. 在数据访问层确保数据一致性
|
|
165
|
-
4. 在业务逻辑层进行类型推导
|
|
212
|
+
创建一个新的 Client 实例。`options` 与 `cassandra-driver` 的 `ClientOptions` 相同。
|
|
166
213
|
|
|
167
|
-
|
|
214
|
+
#### `client.connect(): Promise<void>`
|
|
168
215
|
|
|
169
|
-
|
|
216
|
+
连接到 Cassandra 集群。
|
|
170
217
|
|
|
171
|
-
####
|
|
218
|
+
#### `client.createModel(schema: TableSchema): Model`
|
|
172
219
|
|
|
173
|
-
|
|
174
|
-
constructor(cassandraClient: CassandraClient)
|
|
175
|
-
```
|
|
220
|
+
根据 `TableSchema` 创建一个 `Model` 实例。
|
|
176
221
|
|
|
177
|
-
####
|
|
222
|
+
#### `client.syncSchema(): Promise<void>`
|
|
178
223
|
|
|
179
|
-
|
|
180
|
-
- 设置当前使用的 keyspace,如果不存在则创建
|
|
181
|
-
- `options`:
|
|
182
|
-
- `class`: 复制策略,可以是 `"SimpleStrategy"` 或 `"NetworkTopologyStrategy"`
|
|
183
|
-
- `replication_factor`: 复制因子(仅用于 `SimpleStrategy`)
|
|
184
|
-
- `datacenters`: 数据中心配置(仅用于 `NetworkTopologyStrategy`)
|
|
224
|
+
同步所有通过 `createModel` 创建的模型的 schema。
|
|
185
225
|
|
|
186
|
-
|
|
187
|
-
- 创建并注册一个新的模型
|
|
188
|
-
- 返回的模型实例可以直接使用,不需要额外获取
|
|
226
|
+
#### `client.dropKeyspace(keyspace: string): Promise<void>`
|
|
189
227
|
|
|
190
|
-
|
|
191
|
-
- 同步所有已注册模型的结构到数据库
|
|
228
|
+
删除一个 keyspace。
|
|
192
229
|
|
|
193
|
-
|
|
194
|
-
- 关闭数据库连接
|
|
230
|
+
### `Model`
|
|
195
231
|
|
|
196
|
-
|
|
232
|
+
#### `model.insert(data: T): Promise<void>`
|
|
197
233
|
|
|
198
|
-
|
|
234
|
+
插入一条数据。
|
|
199
235
|
|
|
200
|
-
####
|
|
236
|
+
#### `model.batchInsert(data: T[]): Promise<void>`
|
|
201
237
|
|
|
202
|
-
|
|
203
|
-
// 定义模型 schema
|
|
204
|
-
const userModel = client.createModel({
|
|
205
|
-
id: Field.uuid().partitionKey(), // 分区键,必填
|
|
206
|
-
name: Field.text().clusteringKey(), // 聚类键,必填
|
|
207
|
-
age: Field.int().optional(), // 可选字段
|
|
208
|
-
email: Field.text(), // 普通字段,必填
|
|
209
|
-
}, "users");
|
|
210
|
-
|
|
211
|
-
// 推导出的类型:
|
|
212
|
-
type User = {
|
|
213
|
-
id: string; // 分区键,必填
|
|
214
|
-
name: string; // 聚类键,必填
|
|
215
|
-
age?: number; // 可选字段
|
|
216
|
-
email: string; // 普通字段,必填
|
|
217
|
-
};
|
|
238
|
+
批量插入多条数据。
|
|
218
239
|
|
|
219
|
-
|
|
220
|
-
type PartitionKey = {
|
|
221
|
-
id: string;
|
|
222
|
-
};
|
|
240
|
+
#### `model.find(partitionKey: PK): Promise<T[]>`
|
|
223
241
|
|
|
224
|
-
|
|
225
|
-
type ClusteringKey = {
|
|
226
|
-
name: string;
|
|
227
|
-
};
|
|
242
|
+
根据分区键查询多条数据。
|
|
228
243
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
244
|
+
#### `model.findOne(partitionKey: PK, clusteringKey?: CK): Promise<T | null>`
|
|
245
|
+
|
|
246
|
+
根据分区键和(可选的)聚类键查询单条数据。
|
|
247
|
+
|
|
248
|
+
#### `model.update(partitionKey: PK, data: Partial<T>, clusteringKey?: CK): Promise<void>`
|
|
249
|
+
|
|
250
|
+
更新一条数据。
|
|
251
|
+
|
|
252
|
+
#### `model.delete(partitionKey: PK, clusteringKey?: CK): Promise<void>`
|
|
253
|
+
|
|
254
|
+
删除一条数据。
|
|
235
255
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
- 创建新记录
|
|
240
|
-
- 示例:
|
|
241
|
-
```typescript
|
|
242
|
-
await userModel.create({
|
|
243
|
-
id: uuid(), // 必须提供分区键
|
|
244
|
-
name: "张三", // 必须提供聚类键
|
|
245
|
-
age: 25, // 可选
|
|
246
|
-
email: "zhangsan@example.com" // 必填
|
|
247
|
-
});
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
- `findOne(partitionKey: PartitionKey, clusteringKey?: Partial<ClusteringKey>): Promise<User | null>`
|
|
251
|
-
- 查询单条记录
|
|
252
|
-
- 示例:
|
|
253
|
-
```typescript
|
|
254
|
-
// 只使用分区键查询
|
|
255
|
-
const user = await userModel.findOne({ id: "some-uuid" });
|
|
256
|
-
|
|
257
|
-
// 使用分区键和聚类键查询
|
|
258
|
-
const user = await userModel.findOne(
|
|
259
|
-
{ id: "some-uuid" },
|
|
260
|
-
{ name: "张三" }
|
|
261
|
-
);
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
- `findAll(partitionKey: PartitionKey, clusteringKey?: Partial<ClusteringKey>): Promise<User[]>`
|
|
265
|
-
- 查询多条记录
|
|
266
|
-
- 参数同 `findOne`
|
|
267
|
-
|
|
268
|
-
- `update(partitionKey: PartitionKey, data: Partial<UpdatableFields>): Promise<void>`
|
|
269
|
-
- 更新记录
|
|
270
|
-
- 示例:
|
|
271
|
-
```typescript
|
|
272
|
-
await userModel.update(
|
|
273
|
-
{ id: "some-uuid" }, // 必须提供分区键
|
|
274
|
-
{
|
|
275
|
-
age: 26, // 可以更新可选字段
|
|
276
|
-
email: "new@example.com" // 可以更新普通字段
|
|
277
|
-
}
|
|
278
|
-
);
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
- `delete(partitionKey: PartitionKey, clusteringKey?: Partial<ClusteringKey>): Promise<void>`
|
|
282
|
-
- 删除记录
|
|
283
|
-
- 参数同 `findOne`
|
|
284
|
-
|
|
285
|
-
### Field
|
|
286
|
-
|
|
287
|
-
`Field` 类提供了创建字段配置的方法。
|
|
288
|
-
|
|
289
|
-
#### 静态方法
|
|
290
|
-
|
|
291
|
-
- `uuid(): FieldBuilder<"uuid">`
|
|
292
|
-
- `text(): FieldBuilder<"text">`
|
|
293
|
-
- `int(): FieldBuilder<"int">`
|
|
294
|
-
- `bigint(): FieldBuilder<"bigint">`
|
|
295
|
-
- `float(): FieldBuilder<"float">`
|
|
296
|
-
- `double(): FieldBuilder<"double">`
|
|
297
|
-
- `boolean(): FieldBuilder<"boolean">`
|
|
298
|
-
- `timestamp(): FieldBuilder<"timestamp">`
|
|
299
|
-
|
|
300
|
-
#### 实例方法
|
|
301
|
-
|
|
302
|
-
- `partitionKey(): this`
|
|
303
|
-
- 将字段设置为分区键
|
|
304
|
-
- 分区键字段是必填的,不能为 null
|
|
305
|
-
- 示例:
|
|
306
|
-
```typescript
|
|
307
|
-
Field.uuid().partitionKey() // 将 UUID 字段设置为分区键
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
- `clusteringKey(order?: "ASC" | "DESC"): this`
|
|
311
|
-
- 将字段设置为聚类键
|
|
312
|
-
- 聚类键字段是否必填取决于是否设置了 `optional()`
|
|
313
|
-
- `order` 可选,指定排序方向
|
|
314
|
-
- 示例:
|
|
315
|
-
```typescript
|
|
316
|
-
Field.text().clusteringKey() // 默认升序,必填
|
|
317
|
-
Field.text().clusteringKey("DESC") // 降序,必填
|
|
318
|
-
Field.text().clusteringKey().optional() // 可选聚类键
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
- `optional(): this`
|
|
322
|
-
- 将字段设置为可选
|
|
323
|
-
- 可以用于任何类型的字段,包括聚类键
|
|
324
|
-
- 示例:
|
|
325
|
-
```typescript
|
|
326
|
-
Field.int().optional() // 将整数字段设置为可选
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
- `static(): this`
|
|
330
|
-
- 将字段设置为静态列
|
|
331
|
-
- 静态列在分区级别存储,而不是在每一行重复存储
|
|
332
|
-
- 适用于在分区内所有行共享相同值的字段
|
|
333
|
-
- 示例:
|
|
334
|
-
```typescript
|
|
335
|
-
Field.text().static() // 将文本字段设置为静态列
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
## 注意事项
|
|
339
|
-
|
|
340
|
-
1. 所有模型必须在调用 `syncAllSchemas` 之前创建
|
|
341
|
-
2. 创建记录时必须提供所有分区键字段
|
|
342
|
-
3. 聚类键字段是否必填取决于是否设置了 `optional()`
|
|
343
|
-
4. 更新记录时可以更新非分区键字段(包括聚类键和普通字段)
|
|
344
|
-
5. 删除记录时必须提供所有分区键字段
|
|
345
|
-
|
|
346
|
-
## 许可证
|
|
347
|
-
|
|
348
|
-
MIT
|
|
256
|
+
---
|
|
257
|
+
贡献者:imean
|
|
258
|
+
License: MIT
|