facets

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2025 License: MIT Imports: 6 Imported by: 3

README

The facets package extends HNSW with faceted search capabilities, allowing you to combine vector similarity search with traditional attribute-based filtering.

Features

  • Faceted Nodes: Extend HNSW nodes with facets (attributes)
  • Facet Filtering: Filter search results based on facet values
  • Combined Search: Perform vector similarity search and facet filtering in a single operation
  • Negative Examples: Support for negative examples in faceted search
  • Facet Aggregations: Get aggregated statistics about facet values
Usage
// Create a new HNSW graph
graph := hnsw.NewGraph[int]()

// Create a facet store
store := facets.NewMemoryFacetStore[int]()

// Create a faceted graph
facetedGraph := facets.NewFacetedGraph(graph, store)

// Create a node with facets
node := hnsw.MakeNode(1, []float32{0.1, 0.2, 0.3})
nodeFacets := []facets.Facet{
    facets.NewBasicFacet("category", "Electronics"),
    facets.NewBasicFacet("price", 999.99),
    facets.NewBasicFacet("brand", "TechCo"),
}
facetedNode := facets.NewFacetedNode(node, nodeFacets)

// Add to faceted graph
facetedGraph.Add(facetedNode)

// Search with facet filters
priceFilter := facets.NewRangeFilter("price", 0, 1000)
categoryFilter := facets.NewEqualityFilter("category", "Electronics")

results, err := facetedGraph.Search(
    queryVector,
    []facets.FacetFilter{priceFilter, categoryFilter},
    10, // k
    2,  // expandFactor
)
Facet Types

The package includes several built-in facet types:

  • BasicFacet: Simple facet with a name and value
  • EqualityFilter: Filter that matches facets with equal values
  • RangeFilter: Filter that matches numeric facets within a range
  • StringContainsFilter: Filter that matches string facets containing a substring
Advanced Features
Faceted Search with Negative Examples
results, err := facetedGraph.SearchWithNegative(
    queryVector,
    negativeVector,
    []facets.FacetFilter{categoryFilter},
    10,    // k
    0.7,   // negWeight
    2,     // expandFactor
)
Facet Aggregations
aggregations, err := facetedGraph.GetFacetAggregations(
    queryVector,
    []facets.FacetFilter{categoryFilter},
    []string{"brand", "price"},
    100,  // k
    1,    // expandFactor
)

// Access aggregation results
for value, count := range aggregations["brand"].Values {
    fmt.Printf("Brand %v: %d products\n", value, count)
}

Examples

See the examples directory for complete examples of how to use the extensions:

  • Product Search: Demonstrates faceted search for e-commerce product search

Installation

go get github.com/TFMV/hnsw-extensions

License

Same as the HNSW library.

Documentation

Overview

Package facets provides extensions to the HNSW library for faceted search capabilities.

Package facets provides extensions to the HNSW library for faceted search capabilities.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BasicFacet

type BasicFacet struct {
	// contains filtered or unexported fields
}

BasicFacet is a simple implementation of the Facet interface.

func NewBasicFacet

func NewBasicFacet(name string, value interface{}) BasicFacet

NewBasicFacet creates a new BasicFacet with the given name and value.

func (BasicFacet) Match

func (f BasicFacet) Match(query interface{}) bool

Match checks if this facet matches the given query.

func (BasicFacet) Name

func (f BasicFacet) Name() string

Name returns the name of the facet.

func (BasicFacet) Value

func (f BasicFacet) Value() interface{}

Value returns the value of the facet.

type EqualityFilter

type EqualityFilter struct {
	// contains filtered or unexported fields
}

EqualityFilter is a filter that matches facets with equal values.

func NewEqualityFilter

func NewEqualityFilter(name string, value interface{}) EqualityFilter

NewEqualityFilter creates a new EqualityFilter with the given name and value.

func (EqualityFilter) Matches

func (f EqualityFilter) Matches(value interface{}) bool

Matches checks if a facet value equals this filter's value.

func (EqualityFilter) Name

func (f EqualityFilter) Name() string

Name returns the name of the facet this filter applies to.

type Facet

type Facet interface {
	// Name returns the name of the facet.
	Name() string

	// Value returns the value of the facet.
	Value() interface{}

	// Match checks if this facet matches the given query.
	Match(query interface{}) bool
}

Facet represents a single facet (attribute) that can be attached to a vector.

type FacetAggregation

type FacetAggregation struct {
	Name   string
	Values map[interface{}]int
}

FacetAggregation represents an aggregation of facet values.

type FacetError

type FacetError struct {
	Message string
}

FacetError represents an error related to facet operations.

func (FacetError) Error

func (e FacetError) Error() string

Error returns the error message.

type FacetFilter

type FacetFilter interface {
	// Name returns the name of the facet this filter applies to.
	Name() string

	// Matches checks if a facet value matches this filter.
	Matches(value interface{}) bool
}

FacetFilter defines a filter to be applied on facets.

type FacetStore

type FacetStore[K cmp.Ordered] interface {
	// Add adds a faceted node to the store.
	Add(node FacetedNode[K]) error

	// Get retrieves a faceted node by key.
	Get(key K) (FacetedNode[K], bool)

	// Delete removes a faceted node from the store.
	Delete(key K) bool

	// Filter returns all nodes that match the given filters.
	Filter(filters []FacetFilter) []FacetedNode[K]
}

FacetStore is an interface for storing and retrieving faceted nodes.

type FacetedGraph

type FacetedGraph[K cmp.Ordered] struct {
	Graph *hnsw.Graph[K]
	Store FacetStore[K]
}

FacetedGraph combines an HNSW graph with a facet store for faceted search.

func NewFacetedGraph

func NewFacetedGraph[K cmp.Ordered](graph *hnsw.Graph[K], store FacetStore[K]) *FacetedGraph[K]

NewFacetedGraph creates a new FacetedGraph with the given HNSW graph and facet store.

func (*FacetedGraph[K]) Add

func (fg *FacetedGraph[K]) Add(node FacetedNode[K]) error

Add adds a node with facets to both the graph and the facet store.

func (*FacetedGraph[K]) BatchAdd

func (fg *FacetedGraph[K]) BatchAdd(nodes []FacetedNode[K]) error

BatchAdd adds multiple nodes with facets in a single operation.

func (*FacetedGraph[K]) BatchDelete

func (fg *FacetedGraph[K]) BatchDelete(keys []K) []bool

BatchDelete removes multiple nodes in a single operation.

func (*FacetedGraph[K]) Delete

func (fg *FacetedGraph[K]) Delete(key K) bool

Delete removes a node from both the graph and the facet store.

func (*FacetedGraph[K]) GetFacetAggregations

func (fg *FacetedGraph[K]) GetFacetAggregations(
	query hnsw.Vector,
	filters []FacetFilter,
	facetNames []string,
	k int,
	expandFactor int,
) (map[string]FacetAggregation, error)

GetFacetAggregations returns aggregations of facet values for the given facet names.

func (*FacetedGraph[K]) Search

func (fg *FacetedGraph[K]) Search(
	query hnsw.Vector,
	filters []FacetFilter,
	k int,
	expandFactor int,
) ([]FacetedNode[K], error)

Search performs a faceted search.

func (*FacetedGraph[K]) SearchWithNegative

func (fg *FacetedGraph[K]) SearchWithNegative(
	query hnsw.Vector,
	negative hnsw.Vector,
	filters []FacetFilter,
	k int,
	negWeight float32,
	expandFactor int,
) ([]FacetedNode[K], error)

SearchWithNegative performs a faceted search with a negative example.

type FacetedNode

type FacetedNode[K cmp.Ordered] struct {
	Node   hnsw.Node[K]
	Facets []Facet
}

FacetedNode extends the basic HNSW Node with facets.

func FacetedSearch

func FacetedSearch[K cmp.Ordered](
	graph *hnsw.Graph[K],
	store FacetStore[K],
	query hnsw.Vector,
	filters []FacetFilter,
	k int,
	expandFactor int,
) ([]FacetedNode[K], error)

FacetedSearch performs a search with facet filtering. It first searches for the k*expandFactor nearest neighbors using vector similarity, then filters the results by the given facet filters, and finally returns the top k results.

func FacetedSearchWithNegative

func FacetedSearchWithNegative[K cmp.Ordered](
	graph *hnsw.Graph[K],
	store FacetStore[K],
	query hnsw.Vector,
	negative hnsw.Vector,
	filters []FacetFilter,
	k int,
	negWeight float32,
	expandFactor int,
) ([]FacetedNode[K], error)

FacetedSearchWithNegative performs a search with facet filtering and a negative example. It combines vector similarity search with facet filtering and negative example avoidance.

func NewFacetedNode

func NewFacetedNode[K cmp.Ordered](node hnsw.Node[K], facets []Facet) FacetedNode[K]

NewFacetedNode creates a new FacetedNode with the given node and facets.

func (FacetedNode[K]) GetFacet

func (n FacetedNode[K]) GetFacet(name string) Facet

GetFacet returns the facet with the given name, or nil if not found.

func (FacetedNode[K]) MatchesAllFilters

func (n FacetedNode[K]) MatchesAllFilters(filters []FacetFilter) bool

MatchesAllFilters checks if this node matches all the given filters.

func (FacetedNode[K]) MatchesFilter

func (n FacetedNode[K]) MatchesFilter(filter FacetFilter) bool

MatchesFilter checks if this node matches the given filter.

type MemoryFacetStore

type MemoryFacetStore[K cmp.Ordered] struct {
	// contains filtered or unexported fields
}

MemoryFacetStore is an in-memory implementation of FacetStore.

func NewMemoryFacetStore

func NewMemoryFacetStore[K cmp.Ordered]() *MemoryFacetStore[K]

NewMemoryFacetStore creates a new in-memory facet store.

func (*MemoryFacetStore[K]) Add

func (s *MemoryFacetStore[K]) Add(node FacetedNode[K]) error

Add adds a faceted node to the store.

func (*MemoryFacetStore[K]) Delete

func (s *MemoryFacetStore[K]) Delete(key K) bool

Delete removes a faceted node from the store.

func (*MemoryFacetStore[K]) Filter

func (s *MemoryFacetStore[K]) Filter(filters []FacetFilter) []FacetedNode[K]

Filter returns all nodes that match the given filters.

func (*MemoryFacetStore[K]) Get

func (s *MemoryFacetStore[K]) Get(key K) (FacetedNode[K], bool)

Get retrieves a faceted node by key.

func (*MemoryFacetStore[K]) GetAllNodes added in v0.3.0

func (s *MemoryFacetStore[K]) GetAllNodes() []FacetedNode[K]

GetAllNodes returns all faceted nodes in the store.

type RangeFilter

type RangeFilter struct {
	// contains filtered or unexported fields
}

RangeFilter is a filter that matches numeric facets within a range.

func NewRangeFilter

func NewRangeFilter(name string, min, max float64) RangeFilter

NewRangeFilter creates a new RangeFilter with the given name, min, and max values.

func (RangeFilter) Matches

func (f RangeFilter) Matches(value interface{}) bool

Matches checks if a numeric facet value is within the range.

func (RangeFilter) Name

func (f RangeFilter) Name() string

Name returns the name of the facet this filter applies to.

type StringContainsFilter

type StringContainsFilter struct {
	// contains filtered or unexported fields
}

StringContainsFilter is a filter that matches string facets containing a substring.

func NewStringContainsFilter

func NewStringContainsFilter(name string, contains string) StringContainsFilter

NewStringContainsFilter creates a new StringContainsFilter with the given name and substring.

func (StringContainsFilter) Matches

func (f StringContainsFilter) Matches(value interface{}) bool

Matches checks if a string facet value contains the substring.

func (StringContainsFilter) Name

func (f StringContainsFilter) Name() string

Name returns the name of the facet this filter applies to.

Directories

Path Synopsis
examples
product_search
Package examples provides example implementations of the hnsw-extensions.
Package examples provides example implementations of the hnsw-extensions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL