imean-cassandra-orm 3.3.2 → 4.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 +125 -337
- package/dist/mod.cjs +1077 -2340
- package/dist/mod.d.cts +198 -326
- package/dist/mod.d.ts +198 -326
- package/dist/mod.js +1076 -2338
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -1,337 +1,125 @@
|
|
|
1
|
-
# IMean Cassandra ORM
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## 特性
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
await
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### 4. 批量操作
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
// 批量插入
|
|
132
|
-
const usersData = [
|
|
133
|
-
{
|
|
134
|
-
user_id: "user2",
|
|
135
|
-
email: "user2@example.com",
|
|
136
|
-
name: "王五",
|
|
137
|
-
age: 30,
|
|
138
|
-
is_active: true,
|
|
139
|
-
metadata: { score: 88.0 },
|
|
140
|
-
created_at: new Date(),
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
user_id: "user3",
|
|
144
|
-
email: "user3@example.com",
|
|
145
|
-
name: "赵六",
|
|
146
|
-
age: 28,
|
|
147
|
-
is_active: false,
|
|
148
|
-
metadata: { score: 79.2 },
|
|
149
|
-
created_at: new Date(),
|
|
150
|
-
},
|
|
151
|
-
];
|
|
152
|
-
await userModel.batchInsert(usersData);
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### 5. 使用聚类键
|
|
156
|
-
|
|
157
|
-
当你的 schema 定义了 `clusteringKey` 时,你可以在查询、更新和删除操作中指定它。
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
// 插入带聚类键的数据
|
|
161
|
-
const postData = {
|
|
162
|
-
user_id: "user1",
|
|
163
|
-
post_id: "post1",
|
|
164
|
-
title: "我的第一篇帖子",
|
|
165
|
-
content: "这是内容...",
|
|
166
|
-
tags: ["技术", "编程"],
|
|
167
|
-
published_at: new Date(),
|
|
168
|
-
};
|
|
169
|
-
await postModel.insert(postData);
|
|
170
|
-
|
|
171
|
-
// 查询特定帖子
|
|
172
|
-
const post = await postModel.findOne(
|
|
173
|
-
{ user_id: "user1" },
|
|
174
|
-
{ post_id: "post1" } // 指定聚类键
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
// 更新特定帖子
|
|
178
|
-
await postModel.update(
|
|
179
|
-
{ user_id: "user1" },
|
|
180
|
-
{ title: "更新后的标题" },
|
|
181
|
-
{ post_id: "post1" } // 指定聚类键
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
// 删除特定帖子
|
|
185
|
-
await postModel.delete(
|
|
186
|
-
{ user_id: "user1" },
|
|
187
|
-
{ post_id: "post1" } // 指定聚类键
|
|
188
|
-
);
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### 6. 类型安全与校验
|
|
192
|
-
|
|
193
|
-
ORM 会在数据返回时使用 Zod schema 进行校验,确保你得到的数据是类型安全的。
|
|
194
|
-
|
|
195
|
-
```typescript
|
|
196
|
-
// 从数据库返回的数据
|
|
197
|
-
const userFromDb = await userModel.findOne({ user_id: "user1" });
|
|
198
|
-
|
|
199
|
-
// userFromDb 的类型是根据 userSchema 推断出来的,具有完整的类型提示
|
|
200
|
-
if (userFromDb) {
|
|
201
|
-
console.log(userFromDb.name.toUpperCase());
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// 如果数据库中的数据不符合 schema(例如,手动修改了数据库),
|
|
205
|
-
// 在查询时会抛出 ZodError,防止脏数据进入你的应用。
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
## ClickHouse 双写功能
|
|
209
|
-
|
|
210
|
-
框架支持可选的 ClickHouse 双写功能,可以将 Cassandra 的操作同步到 ClickHouse 中用于分析查询。
|
|
211
|
-
|
|
212
|
-
### 配置双写功能
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
import { Client } from "imean-cassandra-orm";
|
|
216
|
-
|
|
217
|
-
const client = new Client({
|
|
218
|
-
contactPoints: ["localhost"],
|
|
219
|
-
localDataCenter: "datacenter1",
|
|
220
|
-
keyspace: "my_keyspace",
|
|
221
|
-
dualWrite: {
|
|
222
|
-
enabled: true,
|
|
223
|
-
clickhouse: {
|
|
224
|
-
host: "localhost",
|
|
225
|
-
port: 8123,
|
|
226
|
-
username: "default",
|
|
227
|
-
password: "",
|
|
228
|
-
database: "analytics",
|
|
229
|
-
},
|
|
230
|
-
operations: {
|
|
231
|
-
insert: true,
|
|
232
|
-
update: true,
|
|
233
|
-
delete: true,
|
|
234
|
-
},
|
|
235
|
-
errorHandling: "log", // 'ignore' | 'log' | 'throw'
|
|
236
|
-
debug: true,
|
|
237
|
-
},
|
|
238
|
-
});
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### 使用双写功能
|
|
242
|
-
|
|
243
|
-
启用双写后,所有的插入、更新、删除操作都会自动同步到 ClickHouse:
|
|
244
|
-
|
|
245
|
-
```typescript
|
|
246
|
-
// 连接数据库
|
|
247
|
-
await client.connect();
|
|
248
|
-
|
|
249
|
-
// 同步 schema(会自动同步到 ClickHouse)
|
|
250
|
-
await client.syncSchema();
|
|
251
|
-
|
|
252
|
-
// 创建模型
|
|
253
|
-
const UserModel = client.createModel(userSchema);
|
|
254
|
-
|
|
255
|
-
// 插入数据(会自动双写到 ClickHouse)
|
|
256
|
-
await UserModel.insert({
|
|
257
|
-
user_id: "user1",
|
|
258
|
-
email: "user1@example.com",
|
|
259
|
-
name: "张三",
|
|
260
|
-
age: 25,
|
|
261
|
-
is_active: true,
|
|
262
|
-
created_at: new Date(),
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
// 批量插入(会自动双写到 ClickHouse)
|
|
266
|
-
await UserModel.batchInsert([...]);
|
|
267
|
-
|
|
268
|
-
// 更新数据(会自动双写到 ClickHouse)
|
|
269
|
-
await UserModel.update({ user_id: "user1" }, { age: 26 });
|
|
270
|
-
|
|
271
|
-
// 删除数据(会自动双写到 ClickHouse)
|
|
272
|
-
await UserModel.delete({ user_id: "user1" });
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
### 检查双写状态
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
if (client.isDualWriteEnabled()) {
|
|
279
|
-
console.log("双写功能已启用");
|
|
280
|
-
}
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
更多详细信息请参考 [双写功能文档](./docs/dual-write.md)。
|
|
284
|
-
|
|
285
|
-
## API 参考
|
|
286
|
-
|
|
287
|
-
### `Client`
|
|
288
|
-
|
|
289
|
-
#### `new Client(options: cassandra.ClientOptions)`
|
|
290
|
-
|
|
291
|
-
创建一个新的 Client 实例。`options` 与 `cassandra-driver` 的 `ClientOptions` 相同。
|
|
292
|
-
|
|
293
|
-
#### `client.connect(): Promise<void>`
|
|
294
|
-
|
|
295
|
-
连接到 Cassandra 集群。
|
|
296
|
-
|
|
297
|
-
#### `client.createModel(schema: TableSchema): Model`
|
|
298
|
-
|
|
299
|
-
根据 `TableSchema` 创建一个 `Model` 实例。
|
|
300
|
-
|
|
301
|
-
#### `client.syncSchema(): Promise<void>`
|
|
302
|
-
|
|
303
|
-
同步所有通过 `createModel` 创建的模型的 schema。
|
|
304
|
-
|
|
305
|
-
#### `client.dropKeyspace(keyspace: string): Promise<void>`
|
|
306
|
-
|
|
307
|
-
删除一个 keyspace。
|
|
308
|
-
|
|
309
|
-
### `Model`
|
|
310
|
-
|
|
311
|
-
#### `model.insert(data: T): Promise<void>`
|
|
312
|
-
|
|
313
|
-
插入一条数据。
|
|
314
|
-
|
|
315
|
-
#### `model.batchInsert(data: T[]): Promise<void>`
|
|
316
|
-
|
|
317
|
-
批量插入多条数据。
|
|
318
|
-
|
|
319
|
-
#### `model.find(partitionKey: PK): Promise<T[]>`
|
|
320
|
-
|
|
321
|
-
根据分区键查询多条数据。
|
|
322
|
-
|
|
323
|
-
#### `model.findOne(partitionKey: PK, clusteringKey?: CK): Promise<T | null>`
|
|
324
|
-
|
|
325
|
-
根据分区键和(可选的)聚类键查询单条数据。
|
|
326
|
-
|
|
327
|
-
#### `model.update(partitionKey: PK, data: Partial<T>, clusteringKey?: CK): Promise<void>`
|
|
328
|
-
|
|
329
|
-
更新一条数据。
|
|
330
|
-
|
|
331
|
-
#### `model.delete(partitionKey: PK, clusteringKey?: CK): Promise<void>`
|
|
332
|
-
|
|
333
|
-
删除一条数据。
|
|
334
|
-
|
|
335
|
-
---
|
|
336
|
-
贡献者:imean
|
|
337
|
-
License: MIT
|
|
1
|
+
# IMean Cassandra ORM (v2)
|
|
2
|
+
|
|
3
|
+
基于 Zod 的 Cassandra ORM,提供类型安全的 schema 定义、CQL 编译、schema 同步与可选的 ClickHouse 双写。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
- **类型安全**:基于 Zod 的 schema 验证与类型推断
|
|
7
|
+
- **自动 CQL 生成**:CRUD 与查询条件自动编译
|
|
8
|
+
- **Schema 同步**:自动创建与迁移表结构(含索引)
|
|
9
|
+
- **可选双写**:best‑effort 写入 ClickHouse
|
|
10
|
+
- **向量搜索**:支持 ANN 向量检索
|
|
11
|
+
|
|
12
|
+
## 安装
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install imean-cassandra-orm
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 快速开始
|
|
19
|
+
|
|
20
|
+
### 1) 定义 Schema
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
import { defineTable, Types } from "imean-cassandra-orm";
|
|
25
|
+
|
|
26
|
+
const userSchema = defineTable({
|
|
27
|
+
keyspace: "my_keyspace",
|
|
28
|
+
tableName: "users",
|
|
29
|
+
fields: {
|
|
30
|
+
user_id: z.string(),
|
|
31
|
+
email: z.string().email(),
|
|
32
|
+
name: z.string(),
|
|
33
|
+
age: z.number().int().positive(),
|
|
34
|
+
is_active: z.boolean(),
|
|
35
|
+
metadata: Types.json(),
|
|
36
|
+
created_at: z.date(),
|
|
37
|
+
},
|
|
38
|
+
partitionKey: ["user_id"],
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2) 初始化 Client(推荐简化方式)
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { createClientV2 } from "imean-cassandra-orm";
|
|
46
|
+
|
|
47
|
+
const { client, shutdown } = await createClientV2({
|
|
48
|
+
cassandra: {
|
|
49
|
+
contactPoints: ["127.0.0.1"],
|
|
50
|
+
localDataCenter: "datacenter1",
|
|
51
|
+
},
|
|
52
|
+
clickhouse: {
|
|
53
|
+
config: {
|
|
54
|
+
host: "127.0.0.1",
|
|
55
|
+
port: 8123,
|
|
56
|
+
username: "default",
|
|
57
|
+
password: "localpass",
|
|
58
|
+
database: "default",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3) 基本 CRUD
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const userModel = client.model(userSchema);
|
|
68
|
+
await userModel.syncSchema();
|
|
69
|
+
|
|
70
|
+
await userModel.insert({
|
|
71
|
+
user_id: "u1",
|
|
72
|
+
email: "u1@example.com",
|
|
73
|
+
name: "Alice",
|
|
74
|
+
age: 20,
|
|
75
|
+
is_active: true,
|
|
76
|
+
metadata: { score: 95 },
|
|
77
|
+
created_at: new Date(),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const found = await userModel.findOne({ user_id: "u1" });
|
|
81
|
+
await userModel.update({ user_id: "u1" }, { name: "Bob" });
|
|
82
|
+
await userModel.delete({ user_id: "u1" });
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Schema 同步
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
await userModel.syncSchema(); // 自动创建/迁移表结构
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 查询语法
|
|
92
|
+
|
|
93
|
+
详见 `QUERY_SYNTAX.md`。
|
|
94
|
+
|
|
95
|
+
## 向量搜索
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const vectorSchema = defineTable({
|
|
99
|
+
keyspace: "my_keyspace",
|
|
100
|
+
tableName: "docs",
|
|
101
|
+
fields: {
|
|
102
|
+
id: z.string(),
|
|
103
|
+
embedding: Types.vector(128),
|
|
104
|
+
title: z.string(),
|
|
105
|
+
},
|
|
106
|
+
partitionKey: ["id"],
|
|
107
|
+
indexes: {
|
|
108
|
+
embedding: { similarity_function: "COSINE" },
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const model = client.model(vectorSchema);
|
|
113
|
+
await model.syncSchema();
|
|
114
|
+
|
|
115
|
+
const results = await model.find(
|
|
116
|
+
{ embedding: new Array(128).fill(0).map(() => Math.random()) },
|
|
117
|
+
{ limit: 10 }
|
|
118
|
+
);
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 关闭连接
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
await shutdown();
|
|
125
|
+
```
|