159 lines
3.6 KiB
Markdown
159 lines
3.6 KiB
Markdown
# 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` - 技術設計文檔
|
||
|