package index import ( "context" "testing" "time" ) // TestSearchIntegration tests search operations. func TestSearchIntegration(t *testing.T) { if testing.Short() { t.Skip("skipping integration test in short mode") } c := setupIntegrationTest(t) ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() indexName := "test-search-integration" // Setup index with mapping config := &IndexConfig{ Mappings: map[string]any{ "properties": map[string]any{ "title": map[string]any{ "type": "text", }, "category": map[string]any{ "type": "keyword", }, "price": map[string]any{ "type": "integer", }, }, }, } err := CreateIndex(ctx, c, indexName, config) if err != nil { t.Fatalf("setup: CreateIndex() error = %v", err) } defer func() { _ = DeleteIndex(ctx, c, indexName) }() // Index test documents docs := []*Document{ { ID: "1", Source: map[string]any{ "title": "Go Programming Language", "category": "books", "price": 50, }, }, { ID: "2", Source: map[string]any{ "title": "Python for Beginners", "category": "books", "price": 40, }, }, { ID: "3", Source: map[string]any{ "title": "JavaScript Guide", "category": "books", "price": 45, }, }, } err = BulkIndexDocuments(ctx, c, indexName, docs) if err != nil { t.Fatalf("setup: BulkIndexDocuments() error = %v", err) } // Give ES a moment to index time.Sleep(1 * time.Second) // Test 1: Match query t.Run("MatchQuery", func(t *testing.T) { query := &SearchQuery{ Query: MatchQuery("title", "Programming"), Size: 10, } result, err := Search(ctx, c, indexName, query) if err != nil { t.Fatalf("Search() error = %v", err) } if result.Hits.Total.Value == 0 { t.Error("Search() returned no results") } t.Logf("Match query found %d results", result.Hits.Total.Value) }) // Test 2: Term query t.Run("TermQuery", func(t *testing.T) { query := &SearchQuery{ Query: TermQuery("category", "books"), Size: 10, } result, err := Search(ctx, c, indexName, query) if err != nil { t.Fatalf("Search() error = %v", err) } if result.Hits.Total.Value != 3 { t.Errorf("Term query found %d results, want 3", result.Hits.Total.Value) } t.Logf("Term query found %d results", result.Hits.Total.Value) }) // Test 3: Range query t.Run("RangeQuery", func(t *testing.T) { query := &SearchQuery{ Query: RangeQuery("price", 40, 50), Size: 10, } result, err := Search(ctx, c, indexName, query) if err != nil { t.Fatalf("Search() error = %v", err) } if result.Hits.Total.Value == 0 { t.Error("Range query returned no results") } t.Logf("Range query found %d results", result.Hits.Total.Value) }) // Test 4: Bool query t.Run("BoolQuery", func(t *testing.T) { boolQ := &BoolQuery{ Must: []map[string]any{ TermQuery("category", "books"), }, Filter: []map[string]any{ RangeQuery("price", nil, 45), }, } query := &SearchQuery{ Query: boolQ.ToBoolQuery(), Size: 10, } result, err := Search(ctx, c, indexName, query) if err != nil { t.Fatalf("Search() error = %v", err) } if result.Hits.Total.Value == 0 { t.Error("Bool query returned no results") } t.Logf("Bool query found %d results", result.Hits.Total.Value) }) // Test 5: Match all query t.Run("MatchAllQuery", func(t *testing.T) { query := &SearchQuery{ Query: MatchAllQuery(), Size: 10, } result, err := Search(ctx, c, indexName, query) if err != nil { t.Fatalf("Search() error = %v", err) } if result.Hits.Total.Value != 3 { t.Errorf("Match all query found %d results, want 3", result.Hits.Total.Value) } t.Logf("Match all query found %d results", result.Hits.Total.Value) }) // Test 6: Pagination t.Run("Pagination", func(t *testing.T) { query := &SearchQuery{ Query: MatchAllQuery(), Size: 1, From: 1, } result, err := Search(ctx, c, indexName, query) if err != nil { t.Fatalf("Search() error = %v", err) } if len(result.Hits.Hits) != 1 { t.Errorf("Pagination returned %d hits, want 1", len(result.Hits.Hits)) } t.Log("Pagination test passed") }) // Test 7: Multi-match query t.Run("MultiMatchQuery", func(t *testing.T) { query := &SearchQuery{ Query: MultiMatchQuery("Programming", "title", "category"), Size: 10, } result, err := Search(ctx, c, indexName, query) if err != nil { t.Fatalf("Search() error = %v", err) } if result.Hits.Total.Value == 0 { t.Error("Multi-match query returned no results") } t.Logf("Multi-match query found %d results", result.Hits.Total.Value) }) } func TestSearch(t *testing.T) { if testing.Short() { t.Skip("skipping integration test in short mode") } c := setupIntegrationTest(t) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() indexName := "test-search" // Cleanup any existing index first _ = DeleteIndex(ctx, c, indexName) // Setup err := CreateIndex(ctx, c, indexName, nil) if err != nil { t.Fatalf("setup: CreateIndex() error = %v", err) } defer func() { _ = DeleteIndex(ctx, c, indexName) }() // Index a document doc := &Document{ Source: map[string]any{ "message": "test search", }, } _, err = IndexDocument(ctx, c, indexName, doc) if err != nil { t.Fatalf("setup: IndexDocument() error = %v", err) } // Give ES a moment time.Sleep(1 * time.Second) query := &SearchQuery{ Query: MatchAllQuery(), Size: 10, } result, err := Search(ctx, c, indexName, query) if err != nil { t.Fatalf("Search() error = %v", err) } if result == nil { t.Error("Search() returned nil") } t.Logf("Search succeeded: found %d results", result.Hits.Total.Value) } func TestMatchQuery(t *testing.T) { query := MatchQuery("field", "value") if query == nil { t.Error("MatchQuery() returned nil") } if _, ok := query["match"]; !ok { t.Error("MatchQuery() missing 'match' key") } t.Log("MatchQuery test passed") } func TestTermQuery(t *testing.T) { query := TermQuery("field", "value") if query == nil { t.Error("TermQuery() returned nil") } if _, ok := query["term"]; !ok { t.Error("TermQuery() missing 'term' key") } t.Log("TermQuery test passed") } func TestRangeQuery(t *testing.T) { query := RangeQuery("age", 18, 65) if query == nil { t.Error("RangeQuery() returned nil") } if _, ok := query["range"]; !ok { t.Error("RangeQuery() missing 'range' key") } t.Log("RangeQuery test passed") } func TestBoolQuery(t *testing.T) { boolQ := &BoolQuery{ Must: []map[string]any{ MatchQuery("field", "value"), }, } query := boolQ.ToBoolQuery() if query == nil { t.Error("ToBoolQuery() returned nil") } if _, ok := query["bool"]; !ok { t.Error("ToBoolQuery() missing 'bool' key") } t.Log("BoolQuery test passed") }