Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support searching with multiple indexes #5

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
11 changes: 11 additions & 0 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ func (imap *IndexMap[K, V]) GetAllBy(indexName string, key any) []*V {
return values.Collect()
}

// Return all values the seeked by the key,
// nil if index or key not exists.
func (imap *IndexMap[K, V]) GetAllByMulti(indexName string, key any) []*V {
values := imap.getAllBy(indexName, key)
if values == nil {
return nil
}

return values.Collect()
}

// Return true if the value with given key exists,
// false otherwise.
func (imap *IndexMap[K, V]) Contain(key K) bool {
Expand Down
95 changes: 95 additions & 0 deletions search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package indexmap

import (
"github.com/yah01/container"
"github.com/yah01/indexmap/utils"
)

const (
lookupTypeNone lookupType = iota
lookupTypeAnd
lookupTypeOr
lookupTypeExclude
)

type lookupType int

type indexLookup struct {
lookupType lookupType
indexName string
keys []any
}

type SearchStream[K comparable, V any] struct {
chain []*indexLookup

imap *IndexMap[K, V]
}

func (stream *SearchStream[K, V]) And(indexName string, keys ...any) *SearchStream[K, V] {
stream.chain = append(stream.chain, &indexLookup{
lookupType: lookupTypeAnd,
indexName: indexName,
keys: keys,
})

return stream
}

func (stream *SearchStream[K, V]) Or(indexName string, keys ...any) *SearchStream[K, V] {
stream.chain = append(stream.chain, &indexLookup{
lookupType: lookupTypeOr,
indexName: indexName,
keys: keys,
})

return stream
}

func (stream *SearchStream[K, V]) Exclude(indexName string, keys ...any) *SearchStream[K, V] {
stream.chain = append(stream.chain, &indexLookup{
lookupType: lookupTypeExclude,
indexName: indexName,
keys: keys,
})

return stream
}

func (stream *SearchStream[K, V]) Excute() []*V {
values := make(container.Set[*V])

for _, lookup := range stream.chain {
result := stream.executeLookup(lookup)

switch lookup.lookupType {
case lookupTypeAnd:
utils.IntersectSet(values, result)

case lookupTypeOr:
utils.UnionSet(values, result)

case lookupTypeExclude:
utils.ExceptSet(values, result)
}
}

return values.Collect()
}

func (stream *SearchStream[K, V]) executeLookup(lookup *indexLookup) container.Set[*V] {
result := make(container.Set[*V])
for i := range lookup.keys {
utils.UnionSet(result,
stream.imap.getAllBy(lookup.indexName, lookup.keys[i]))
}

return result
}

func (imap *IndexMap[K, V]) Search() *SearchStream[K, V] {
return &SearchStream[K, V]{
chain: make([]*indexLookup, 0),
imap: imap,
}
}
7 changes: 7 additions & 0 deletions search_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package indexmap

import "testing"

func TestSearch(t *testing.T) {

}
23 changes: 23 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package utils

import "github.com/yah01/container"

func UnionSet[T comparable](dst container.Set[T], src container.Set[T]) {
for elem := range src {
dst.Insert(elem)
}
}

func IntersectSet[T comparable](dst container.Set[T], src container.Set[T]) {
for elem := range dst {
if !src.Contain(elem) {
delete(dst, elem)
}
}
}

func ExceptSet[T comparable](dst container.Set[T], src container.Set[T]) {
for elem := range src {
delete(dst, elem)
}
}