about summary refs log tree commit diff stats
path: root/internal
diff options
context:
space:
mode:
authorAlan Pearce2025-03-21 21:55:00 +0100
committerAlan Pearce2025-03-21 21:55:00 +0100
commit9c9aa6b408812248c9f8c29ecc3546ef64947ea8 (patch)
treeb99f6e9f62f232db8fff7499a6ddab0b287b5ea3 /internal
parente8fbdf3bd12c8920a6e9bd84b34e787764b11eaf (diff)
downloadsearchix-9c9aa6b408812248c9f8c29ecc3546ef64947ea8.tar.lz
searchix-9c9aa6b408812248c9f8c29ecc3546ef64947ea8.tar.zst
searchix-9c9aa6b408812248c9f8c29ecc3546ef64947ea8.zip
perf: iterate over results without keeping the set in memory
Diffstat (limited to 'internal')
-rw-r--r--internal/components/combined.go2
-rw-r--r--internal/components/options.go2
-rw-r--r--internal/components/packages.go2
-rw-r--r--internal/index/search.go45
4 files changed, 33 insertions, 18 deletions
diff --git a/internal/components/combined.go b/internal/components/combined.go
index d8c6fea..fe97e14 100644
--- a/internal/components/combined.go
+++ b/internal/components/combined.go
@@ -36,7 +36,7 @@ func Combined(result *index.Result) g.Node {
 			),
 		),
 		TBody(
-			g.Map(result.Hits, func(hit index.DocumentMatch) g.Node {
+			g.MapIter(result.Hits, func(hit index.DocumentMatch) g.Node {
 				return Tr(
 					Td(
 						openCombinedDialogLink(nix.GetKey(hit.Data)),
diff --git a/internal/components/options.go b/internal/components/options.go
index af6c73f..1d01784 100644
--- a/internal/components/options.go
+++ b/internal/components/options.go
@@ -21,7 +21,7 @@ func Options(result *index.Result) g.Node {
 			),
 		),
 		TBody(
-			g.Map(result.Hits, func(hit index.DocumentMatch) g.Node {
+			g.MapIter(result.Hits, func(hit index.DocumentMatch) g.Node {
 				if m := convertMatch[nix.Option](hit.Data); m != nil {
 					return optionRow(hit, *m)
 				}
diff --git a/internal/components/packages.go b/internal/components/packages.go
index 9bc3f99..db45302 100644
--- a/internal/components/packages.go
+++ b/internal/components/packages.go
@@ -22,7 +22,7 @@ func Packages(result *index.Result) g.Node {
 			),
 		),
 		TBody(
-			g.Map(result.Hits, func(hit index.DocumentMatch) g.Node {
+			g.MapIter(result.Hits, func(hit index.DocumentMatch) g.Node {
 				if m := convertMatch[nix.Package](hit.Data); m != nil {
 					return packageRow(hit, *m)
 				}
diff --git a/internal/index/search.go b/internal/index/search.go
index 3f24799..292661e 100644
--- a/internal/index/search.go
+++ b/internal/index/search.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"context"
 	"encoding/gob"
+	"iter"
 	"time"
 
 	"go.alanpearce.eu/searchix/internal/config"
@@ -25,7 +26,7 @@ type DocumentMatch struct {
 
 type Result struct {
 	*bleve.SearchResult
-	Hits []DocumentMatch
+	Hits iter.Seq[DocumentMatch]
 }
 
 type ReadIndex struct {
@@ -87,24 +88,31 @@ func (index *ReadIndex) search(
 			return nil, errors.WithMessage(err, "failed to execute search query")
 		}
 
-		results := make([]DocumentMatch, bleveResult.Hits.Len())
-		var buf bytes.Buffer
-		for i, result := range bleveResult.Hits {
-			results[i].DocumentMatch = bleveResult.Hits[i]
-			_, err = buf.WriteString(result.Fields["_data"].(string))
-			if err != nil {
-				return nil, errors.WithMessage(err, "error fetching result data")
+		hits := func(yield func(DocumentMatch) bool) {
+			var buf bytes.Buffer
+			for _, match := range bleveResult.Hits {
+				hit := DocumentMatch{
+					DocumentMatch: match,
+					Data:          nil,
+				}
+				_, err := buf.WriteString(match.Fields["_data"].(string))
+				if err != nil {
+					index.log.Warn("error fetching result data", "error", err)
+				}
+				err = gob.NewDecoder(&buf).Decode(&hit.Data)
+				if err != nil {
+					index.log.Warn("error decoding gob data", "error", err, "data", buf.String())
+				}
+				buf.Reset()
+				if !yield(hit) {
+					return
+				}
 			}
-			err = gob.NewDecoder(&buf).Decode(&results[i].Data)
-			if err != nil {
-				return nil, errors.WithMessagef(err, "error decoding gob data: %s", buf.String())
-			}
-			buf.Reset()
 		}
 
 		return &Result{
 			SearchResult: bleveResult,
-			Hits:         results,
+			Hits:         hits,
 		}, nil
 	}
 }
@@ -188,6 +196,7 @@ func (index *ReadIndex) GetDocument(
 	key := nix.MakeKey(source, id)
 	query := bleve.NewDocIDQuery([]string{key})
 	search := bleve.NewSearchRequest(query)
+	search.Size = 1
 
 	result, err := index.search(ctx, search)
 	if err != nil {
@@ -198,5 +207,11 @@ func (index *ReadIndex) GetDocument(
 		return nil, nil
 	}
 
-	return &result.Hits[0].Data, err
+	for hit := range result.Hits {
+		if hit.ID == key {
+			return &hit.Data, err
+		}
+	}
+
+	return nil, err
 }