feat(12-01): report the search engine's found count and field weights
- optional beachcomber.PageSearcher returns a page of candidate ids plus the engine's found count; beachcomber.SearchPage falls back to SearchIDs for engines without it, so Engine is unchanged - Query.QueryByWeights is sent to Typesense as query_by_weights; a mismatched weight list or a page above typesense.MaxPerPage (250) is refused before any request
This commit is contained in:
80
modules/beachcomber/searchpage_test.go
Normal file
80
modules/beachcomber/searchpage_test.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package beachcomber
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// idsOnlyEngine implements Engine without PageSearcher.
|
||||
type idsOnlyEngine struct {
|
||||
ids []string
|
||||
err error
|
||||
got Query
|
||||
}
|
||||
|
||||
func (*idsOnlyEngine) Name() string { return "ids-only" }
|
||||
func (*idsOnlyEngine) Configured() bool { return true }
|
||||
func (*idsOnlyEngine) Upsert(context.Context, string, map[string]any, []map[string]any) error {
|
||||
return nil
|
||||
}
|
||||
func (*idsOnlyEngine) Delete(context.Context, string, []string) error { return nil }
|
||||
func (*idsOnlyEngine) Flush(context.Context, string) error { return nil }
|
||||
|
||||
func (e *idsOnlyEngine) SearchIDs(_ context.Context, _ string, q Query) ([]string, error) {
|
||||
e.got = q
|
||||
return e.ids, e.err
|
||||
}
|
||||
|
||||
// pagedEngine implements PageSearcher.
|
||||
type pagedEngine struct {
|
||||
idsOnlyEngine
|
||||
found int
|
||||
}
|
||||
|
||||
func (e *pagedEngine) SearchPage(_ context.Context, _ string, q Query) (SearchResult, error) {
|
||||
e.got = q
|
||||
return SearchResult{IDs: e.ids, Found: e.found}, nil
|
||||
}
|
||||
|
||||
func TestSearchPageFallsBackToSearchIDs(t *testing.T) {
|
||||
e := &idsOnlyEngine{ids: []string{"3", "1"}}
|
||||
q := Query{Q: "blue", QueryBy: []string{"name", "notes"}, QueryByWeights: []int{10, 1}, PerPage: 20}
|
||||
res, err := SearchPage(context.Background(), e, "posts", q)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(res, SearchResult{IDs: []string{"3", "1"}, Found: 2}) {
|
||||
t.Fatalf("res = %+v", res)
|
||||
}
|
||||
if !reflect.DeepEqual(e.got, q) {
|
||||
t.Fatalf("query = %+v", e.got)
|
||||
}
|
||||
e.err = errors.New("down")
|
||||
if _, err := SearchPage(context.Background(), e, "posts", q); err == nil {
|
||||
t.Fatal("engine error must surface")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchPageUsesPageSearcher(t *testing.T) {
|
||||
e := &pagedEngine{idsOnlyEngine: idsOnlyEngine{ids: []string{"7"}}, found: 1234}
|
||||
res, err := SearchPage(context.Background(), e, "posts", Query{Q: "x"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if res.Found != 1234 || !reflect.DeepEqual(res.IDs, []string{"7"}) {
|
||||
t.Fatalf("res = %+v", res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchPageNullEngine(t *testing.T) {
|
||||
var e Engine = nullEngine{}
|
||||
if _, ok := e.(PageSearcher); !ok {
|
||||
t.Fatal("the null engine implements PageSearcher")
|
||||
}
|
||||
res, err := SearchPage(context.Background(), e, "posts", Query{})
|
||||
if err != nil || res.Found != 0 || res.IDs == nil || len(res.IDs) != 0 {
|
||||
t.Fatalf("res = %+v err = %v", res, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user