package main import ( "fmt" "log" "os" "path/filepath" "time" "linedb/pkg/linedb" ) // Пример работы с партициями + индексируемой коллекцией. // // Запуск: // go run ./examples/partitions/main.go // // Важно: // - В текущей реализации индексы строятся для "обычных" коллекций. // - Партиционированные коллекции (партиции) создаются динамически и сейчас не индексируются // (см. getPartitionAdapter: JSONLFileOptions{CollectionName: partitionName} без IndexedFields). func main() { dbDir := filepath.Join(".", "examples", "partitions", "data") _ = os.RemoveAll(dbDir) if err := os.MkdirAll(dbDir, 0755); err != nil { log.Fatalf("mkdir: %v", err) } // Настройка: // - users: обычная коллекция с индексами // - events: базовая коллекция для партиций (сама по себе не используется для записи), // а реальные данные будут в events_.jsonl initOptions := &linedb.LineDbInitOptions{ DBFolder: dbDir, Collections: []linedb.JSONLFileOptions{ { CollectionName: "users", AllocSize: 512, IndexedFields: []string{"id", "email"}, }, { CollectionName: "events", AllocSize: 512, }, }, Partitions: []linedb.PartitionCollection{ { CollectionName: "events", PartIDFn: func(v any) string { m, ok := v.(map[string]any) if !ok { return "unknown" } tenant, ok := m["tenant"].(string) if !ok || tenant == "" { return "unknown" } return tenant }, }, }, } db := linedb.NewLineDb(&linedb.LineDbOptions{ IndexStore: linedb.NewInMemoryIndexStore(), }) if err := db.Init(true, initOptions); err != nil { log.Fatalf("Init failed: %v", err) } defer db.Close() fmt.Println("=== 1) Индексируемая коллекция users ===") users := []any{ map[string]any{"id": 1, "email": "a@example.com", "name": "Alice", "createdAt": time.Now().Format(time.RFC3339Nano)}, map[string]any{"id": 2, "email": "b@example.com", "name": "Bob", "createdAt": time.Now().Format(time.RFC3339Nano)}, } // Используем Write + DoIndexing: true, чтобы индекс был актуален сразу после записи. if err := db.Write(users, "users", linedb.LineDbAdapterOptions{DoIndexing: true}); err != nil { log.Fatalf("Write users failed: %v", err) } byEmail, err := db.ReadByFilter(map[string]any{"email": "a@example.com"}, "users", linedb.LineDbAdapterOptions{}) if err != nil { log.Fatalf("ReadByFilter users by email failed: %v", err) } mustLen("users by email", byEmail, 1) byID, err := db.ReadByFilter(map[string]any{"id": 2}, "users", linedb.LineDbAdapterOptions{}) if err != nil { log.Fatalf("ReadByFilter users by id failed: %v", err) } mustLen("users by id", byID, 1) fmt.Println("OK: users inserted and searchable by indexed fields (id/email).") fmt.Println("\n=== 2) Партиционированная коллекция events (events_) ===") events := []any{ map[string]any{"id": 1, "tenant": "A", "type": "signup", "status": "new", "ts": time.Now().Unix()}, map[string]any{"id": 2, "tenant": "A", "type": "purchase", "status": "new", "ts": time.Now().Unix()}, map[string]any{"id": 3, "tenant": "B", "type": "signup", "status": "new", "ts": time.Now().Unix()}, } if err := db.Insert(events, "events", linedb.LineDbAdapterOptions{}); err != nil { log.Fatalf("Insert events failed: %v", err) } tenantA, err := db.ReadByFilter(map[string]any{"tenant": "A"}, "events", linedb.LineDbAdapterOptions{}) if err != nil { log.Fatalf("ReadByFilter events tenant A failed: %v", err) } mustLen("events tenant A after insert", tenantA, 2) tenantB, err := db.ReadByFilter(map[string]any{"tenant": "B"}, "events", linedb.LineDbAdapterOptions{}) if err != nil { log.Fatalf("ReadByFilter events tenant B failed: %v", err) } mustLen("events tenant B after insert", tenantB, 1) fmt.Println("OK: события разложены по партициям (A и B).") fmt.Println("\n=== 3) Update по всем партициям ===") updated, err := db.Update( map[string]any{"status": "processed"}, "events", map[string]any{"tenant": "A"}, linedb.LineDbAdapterOptions{}, ) if err != nil { log.Fatalf("Update events failed: %v", err) } mustLen("updated events for tenant A", updated, 2) processedA, err := db.ReadByFilter(map[string]any{"tenant": "A", "status": "processed"}, "events", linedb.LineDbAdapterOptions{}) if err != nil { log.Fatalf("ReadByFilter processed events failed: %v", err) } mustLen("processed events for tenant A", processedA, 2) fmt.Println("OK: обновление затронуло записи в партиции A.") fmt.Println("\n=== 4) Delete по всем партициям ===") deleted, err := db.Delete(map[string]any{"id": 3}, "events", linedb.LineDbAdapterOptions{}) if err != nil { log.Fatalf("Delete events failed: %v", err) } mustLen("deleted events id=3", deleted, 1) allRemaining, err := db.ReadByFilter(nil, "events", linedb.LineDbAdapterOptions{}) if err != nil { log.Fatalf("ReadByFilter all remaining events failed: %v", err) } mustLen("remaining events after delete", allRemaining, 2) fmt.Printf("\nГотово. Данные примера в: %s\n", dbDir) } func mustLen(label string, got []any, want int) { if len(got) != want { log.Fatalf("%s: expected %d, got %d (%v)", label, want, len(got), got) } }