Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ jobs:
test:
strategy:
matrix:
go-version: [1.20.x, 1.21.x, 1.22.x]
go-version: [1.23.x, 1.24.x, 1.25.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- name: Install Go
uses: actions/setup-go@v1
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
Expand Down
8 changes: 8 additions & 0 deletions document.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,11 @@ type SynonymDocument interface {
// The provided visitor function is called for each synonym field.
VisitSynonymFields(visitor SynonymFieldVisitor)
}

// NestedDocument is a document that contains other documents inside it.
type NestedDocument interface {
Document
// VisitNestedDocuments allows iteration over all nested documents in the document.
// The provided visitor function is called for each nested document.
VisitNestedDocuments(visitor func(doc Document))
}
78 changes: 77 additions & 1 deletion index.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package index
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"reflect"
)

Expand Down Expand Up @@ -185,17 +187,46 @@ func (tfv *TermFieldVector) Size() int {
len(tfv.Field) + len(tfv.ArrayPositions)*sizeOfUint64
}

// IndexInternalID is an opaque document identifier interal to the index impl
// IndexInternalID is an opaque document identifier internal to the index impl
type IndexInternalID []byte

// NewIndexInternalID encodes a uint64 into an 8-byte big-endian ID, reusing `buf` when possible.
func NewIndexInternalID(buf []byte, in uint64) IndexInternalID {
if len(buf) != 8 {
if cap(buf) >= 8 {
buf = buf[0:8]
} else {
buf = make([]byte, 8)
}
}
binary.BigEndian.PutUint64(buf, in)
return buf
}

// NewIndexInternalIDFrom creates a new IndexInternalID by copying from `other`, reusing `buf` when possible.
func NewIndexInternalIDFrom(buf IndexInternalID, other IndexInternalID) IndexInternalID {
buf = buf[:0]
return append(buf, other...)
}

// Equals checks if two IndexInternalID values are equal.
func (id IndexInternalID) Equals(other IndexInternalID) bool {
return id.Compare(other) == 0
}

// Compare compares two IndexInternalID values, inherently comparing the encoded uint64 values.
func (id IndexInternalID) Compare(other IndexInternalID) int {
return bytes.Compare(id, other)
}

// Value returns the uint64 value encoded in the IndexInternalID.
func (id IndexInternalID) Value() (uint64, error) {
if len(id) != 8 {
return 0, fmt.Errorf("wrong len for IndexInternalID: %q", id)
}
return binary.BigEndian.Uint64(id), nil
}

type TermFieldDoc struct {
Term string
ID IndexInternalID
Expand Down Expand Up @@ -391,3 +422,48 @@ type IndexInsightsReader interface {
// cluster densities (or cardinalities)
CentroidCardinalities(field string, limit int, descending bool) (cenCards []CentroidCardinality, err error)
}

// -----------------------------------------------------------------------------
// NestedReader is an extended index reader that supports hierarchical document structures.
type NestedReader interface {
IndexReader
// Ancestors returns the ancestral chain for a given document ID in the index.
// For nested documents, this method retrieves all parent documents in the hierarchy
// leading up to the root document ID.
Ancestors(id IndexInternalID, prealloc []AncestorID) ([]AncestorID, error)
}

// AncestorID represents the identifier of an ancestor document in an ancestor chain.
type AncestorID uint64

// NewAncestorID creates a new AncestorID from the given uint64 value.
func NewAncestorID(val uint64) AncestorID {
return AncestorID(val)
}

// Compare compares two AncestorID values.
func (a AncestorID) Compare(b AncestorID) int {
switch {
case a < b:
return -1
case a > b:
return 1
default:
return 0
}
}

// Equals checks if two AncestorID values are equal.
func (a AncestorID) Equals(b AncestorID) bool {
return a == b
}

// Add returns a new AncestorID by adding the given uint64 value to the current AncestorID.
func (a AncestorID) Add(n uint64) AncestorID {
return AncestorID(uint64(a) + n)
}

// ToIndexInternalID converts the AncestorID to an IndexInternalID.
func (a AncestorID) ToIndexInternalID(prealloc IndexInternalID) IndexInternalID {
return NewIndexInternalID(prealloc, uint64(a))
}
Loading