backend/pkg/library/cassandra/README.md

159 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Cassandra2 - 新一代 Cassandra 客戶端
Cassandra2 是重新設計的 Cassandra 客戶端,提供更簡潔的 API、更好的類型安全性和更清晰的架構。
## 特色
-**Repository 模式**:每個 Repository 綁定一個 keyspace無需到處傳遞
-**類型安全**:使用泛型,編譯期類型檢查
-**簡潔的 API**:統一的查詢介面,流暢的鏈式調用
-**符合 cursor.md 原則**:小介面、依賴注入、顯式錯誤處理
## 快速開始
### 1. 初始化
```go
import "your-module/pkg/library/cassandra"
// 創建 DB 連接
db, err := cassandra2.New(
cassandra2.WithHosts("localhost"),
cassandra2.WithKeyspace("my_keyspace"),
cassandra2.WithPort(9042),
)
if err != nil {
log.Fatal(err)
}
defer db.Close()
```
### 2. 定義資料模型
```go
type User struct {
ID gocql.UUID `db:"id" partition_key:"true"`
Name string `db:"name"`
Email string `db:"email"`
CreatedAt time.Time `db:"created_at"`
}
func (u User) TableName() string {
return "users"
}
```
### 3. 使用 Repository
```go
// 獲取 Repository
repo, err := db.Repository[User]("my_keyspace")
// 插入
user := User{
ID: gocql.TimeUUID(),
Name: "Alice",
Email: "alice@example.com",
CreatedAt: time.Now(),
}
err = repo.Insert(ctx, user)
// 查詢
var result User
result, err = repo.Get(ctx, user.ID)
// 更新
user.Email = "newemail@example.com"
err = repo.Update(ctx, user)
// 刪除
err = repo.Delete(ctx, user.ID)
```
### 4. 使用 Query Builder
```go
// 條件查詢
var users []User
err = repo.Query().
Where(cassandra2.Eq("status", "active")).
OrderBy("created_at", cassandra2.DESC).
Limit(10).
Scan(ctx, &users)
// 單筆查詢
user, err := repo.Query().
Where(cassandra2.Eq("id", userID)).
One(ctx)
// 計數
count, err := repo.Query().
Where(cassandra2.Eq("status", "active")).
Count(ctx)
```
### 5. Batch 操作
```go
batch := repo.Batch(ctx)
batch.Insert(user1).
Insert(user2).
Update(user3)
err = batch.Commit(ctx)
```
### 6. Transaction 操作
```go
tx := db.Begin(ctx, "my_keyspace")
tx.Insert(user1)
tx.Update(user2)
if err := tx.Commit(ctx); err != nil {
tx.Rollback(ctx)
}
```
## API 對比
### 舊 API (Cassandra 1)
```go
db.Insert(ctx, user, "keyspace")
db.Model(ctx, &User{}, "keyspace").Where(...).Scan(&result)
```
### 新 API (Cassandra 2)
```go
repo := db.Repository[User]("keyspace")
repo.Insert(ctx, user)
repo.Query().Where(...).Scan(ctx, &result)
```
## 主要改進
1. **移除 keyspace 參數**Repository 綁定 keyspace無需重複傳遞
2. **類型安全**:使用泛型,編譯期檢查
3. **統一 API**:只有一套查詢介面
4. **更好的錯誤處理**:統一的錯誤類型,支援 errors.Is/As
## 注意事項
1. **主鍵查詢**`Get` 方法需要完整的 Primary Key。如果是多欄位主鍵需要傳入包含所有主鍵欄位的 struct。
2. **更新行為**`Update` 預設只更新非零值欄位,使用 `UpdateAll` 可更新所有欄位。
3. **Transaction**:這是補償式交易,不是真正的 ACID 交易,適用於最終一致性場景。
## 遷移指南
從 Cassandra 1 遷移到 Cassandra 2
1.`cassandra.NewCassandraDB` 改為 `cassandra2.New`
2.`db.Insert(ctx, doc, keyspace)` 改為 `repo.Insert(ctx, doc)`,其中 `repo = db.Repository[Type](keyspace)`
3.`db.Model(...)` 改為 `repo.Query()`
4. 更新錯誤處理:使用 `cassandra2.IsNotFound` 等函數
## 文檔
詳細的技術設計請參考:
- `REFACTORING_PLAN.md` - 重構計畫
- `TECHNICAL_DESIGN.md` - 技術設計文檔