Skip to content

Commit ac6bc3d

Browse files
version2
1 parent bdd9010 commit ac6bc3d

File tree

4 files changed

+93
-16
lines changed

4 files changed

+93
-16
lines changed

index/scorch/snapshot_index.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -622,10 +622,10 @@ func (is *IndexSnapshot) TermFieldReader(ctx context.Context, term []byte, field
622622
rv.includeTermVectors = includeTermVectors
623623
rv.currPosting = nil
624624
rv.currID = rv.currID[:0]
625-
rv.nestInfo = nil
625+
rv.nestedState = nil
626626
if ctx != nil {
627-
if nInfo, ok := ctx.Value(search.NestedInfoCallbackKey).(*search.NestedInfo); ok {
628-
rv.nestInfo = nInfo
627+
if nestedState, ok := ctx.Value(search.NestedStateKey).(index.NestedState); ok {
628+
rv.nestedState = nestedState
629629
}
630630
}
631631

@@ -643,8 +643,8 @@ func (is *IndexSnapshot) TermFieldReader(ctx context.Context, term []byte, field
643643
}
644644
var dict segment.TermDictionary
645645
var err error
646-
if nestedSegment, ok := s.segment.(segment.NestedSegment); ok && rv.nestInfo != nil {
647-
dict, err = nestedSegment.NestedDictionary(field, rv.nestInfo.Path, rv.nestInfo.ArrayPosition)
646+
if ns, ok := s.segment.(segment.NestedSegment); ok && rv.nestedState != nil {
647+
dict, err = ns.NestedDictionary(rv.nestedState, field)
648648
} else {
649649
dict, err = s.segment.Dictionary(field)
650650
}

index/scorch/snapshot_index_tfr.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type IndexSnapshotTermFieldReader struct {
5151
bytesRead uint64
5252
ctx context.Context
5353
unadorned bool
54-
nestInfo *search.NestedInfo
54+
nestedState index.NestedState
5555
}
5656

5757
func (i *IndexSnapshotTermFieldReader) incrementBytesRead(val uint64) {

search/query/nested.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,23 @@ func (q *NestedQuery) Searcher(ctx context.Context, i index.IndexReader, m mappi
4343
if !ok {
4444
return nil, fmt.Errorf("nested searcher requires an index reader that supports nested documents")
4545
}
46-
childCount := nr.ChildCount(q.Path)
46+
if q.Path == "" || q.InnerQuery == nil {
47+
return nil, fmt.Errorf("nested searcher requires a valid path and inner query")
48+
}
49+
var baseState index.NestedState
50+
if existing, ok := ctx.Value(search.NestedStateKey).(index.NestedState); ok {
51+
baseState = existing
52+
} else {
53+
baseState = search.NewNestedState()
54+
}
55+
childCount := nr.ChildCount(baseState, q.Path)
4756
if childCount == 0 {
4857
return nil, fmt.Errorf("nested searcher: path %q has no child documents", q.Path)
4958
}
5059
innerSearchers := make([]search.Searcher, 0, childCount)
51-
for arrayPos := range childCount {
52-
nctx := context.WithValue(ctx, search.NestedInfoCallbackKey, &search.NestedInfo{
53-
Path: q.Path,
54-
ArrayPosition: arrayPos,
55-
})
60+
for arrayPos := 0; arrayPos < childCount; arrayPos++ {
61+
newState := baseState.Append(q.Path, arrayPos)
62+
nctx := context.WithValue(ctx, search.NestedStateKey, newState)
5663
innerSearcher, err := q.InnerQuery.Searcher(nctx, i, m, options)
5764
if err != nil {
5865
return nil, fmt.Errorf("nested searcher: failed to create inner searcher at pos %d: %w", arrayPos, err)

search/util.go

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ package search
1616

1717
import (
1818
"context"
19+
"slices"
1920

21+
index "github.com/blevesearch/bleve_index_api"
2022
"github.com/blevesearch/geo/s2"
2123
)
2224

@@ -153,7 +155,7 @@ const (
153155
// to the actual search phase which would use it to perform the search.
154156
BM25StatsKey ContextKey = "_bm25_stats_key"
155157

156-
NestedInfoCallbackKey ContextKey = "_nested_info_callback_key"
158+
NestedStateKey ContextKey = "_nested_state_key"
157159
)
158160

159161
func RecordSearchCost(ctx context.Context,
@@ -236,7 +238,75 @@ type BM25Stats struct {
236238
FieldCardinality map[string]int `json:"field_cardinality"`
237239
}
238240

239-
type NestedInfo struct {
240-
Path string `json:"path"`
241-
ArrayPosition int `json:"array_position"`
241+
type nestedState struct {
242+
paths []string
243+
arrayPositions []int
244+
}
245+
246+
func NewNestedState() index.NestedState {
247+
return &nestedState{
248+
paths: make([]string, 0),
249+
arrayPositions: make([]int, 0),
250+
}
251+
}
252+
253+
// Append returns a new NestedState with the given path and array position added.
254+
// It does NOT modify the original NestedState.
255+
func (s *nestedState) Append(path string, pos int) index.NestedState {
256+
return &nestedState{
257+
paths: append(slices.Clone(s.paths), path),
258+
arrayPositions: append(slices.Clone(s.arrayPositions), pos),
259+
}
260+
}
261+
262+
func (s *nestedState) Empty() bool {
263+
return len(s.paths) == 0 && len(s.arrayPositions) == 0
264+
}
265+
266+
func (s *nestedState) Clear() {
267+
s.paths = s.paths[:0]
268+
s.arrayPositions = s.arrayPositions[:0]
269+
}
270+
271+
func (s *nestedState) Root() string {
272+
if len(s.paths) == 0 {
273+
return ""
274+
}
275+
return s.paths[0]
276+
}
277+
278+
func (s *nestedState) Iterator() index.NestedIterator {
279+
return &nestedIterator{
280+
paths: s.paths,
281+
arrayPosition: s.arrayPositions,
282+
index: 0,
283+
}
284+
}
285+
286+
type nestedIterator struct {
287+
paths []string
288+
arrayPosition []int
289+
index int
290+
}
291+
292+
func (ni *nestedIterator) HasNext() bool {
293+
return ni.index < len(ni.paths)
294+
}
295+
296+
func (ni *nestedIterator) Next() (string, int, bool) {
297+
if ni.index >= len(ni.paths) {
298+
return "", 0, false
299+
}
300+
path := ni.paths[ni.index]
301+
arrayPos := ni.arrayPosition[ni.index]
302+
ni.index++
303+
return path, arrayPos, true
304+
}
305+
306+
func (ni *nestedIterator) Reset() {
307+
ni.index = 0
308+
}
309+
310+
func (ni *nestedIterator) Size() int {
311+
return len(ni.paths)
242312
}

0 commit comments

Comments
 (0)