package storage import ( "context" "errors" "fmt" "local/dndex/storage/driver" "local/dndex/storage/entity" "local/dndex/storage/operator" "go.mongodb.org/mongo-driver/bson" ) type Graph struct { driver driver.Driver } func NewGraph(path ...string) Graph { return Graph{ driver: driver.New(path...), } } func (g Graph) Search(ctx context.Context, namespace string, nameContains string) ([]entity.One, error) { filter := operator.Regex{Key: entity.Name, Value: fmt.Sprintf(".*%s.*", nameContains)} return g.find(ctx, namespace, filter) } func (g Graph) ListCaseInsensitive(ctx context.Context, namespace string, from ...string) ([]entity.One, error) { filter := operator.CaseInsensitives{Key: entity.Name, Values: from} return g.find(ctx, namespace, filter) } func (g Graph) Get(ctx context.Context, namespace, id string) (entity.One, error) { ones, err := g.find(ctx, namespace, bson.M{entity.ID: id}) if err != nil { return entity.One{}, err } if len(ones) == 0 { return entity.One{}, errors.New("not found") } if len(ones) > 1 { return entity.One{}, errors.New("primary key collision detected") } return ones[0], nil } func (g Graph) List(ctx context.Context, namespace string, from ...string) ([]entity.One, error) { filter := operator.NewFilterIn(entity.Name, from) return g.find(ctx, namespace, filter) } func (g Graph) find(ctx context.Context, namespace string, filter interface{}) ([]entity.One, error) { ch, err := g.driver.Find(ctx, namespace, filter) if err != nil { return nil, err } return g.gatherOnes(ctx, ch) } func (g Graph) gatherOnes(ctx context.Context, ch <-chan bson.Raw) ([]entity.One, error) { var ones []entity.One for one := range ch { var o entity.One if err := bson.Unmarshal(one, &o); err != nil { return nil, err } ones = append(ones, o) } return ones, nil } func (g Graph) Insert(ctx context.Context, namespace string, one entity.One) error { if one.Name == "" || one.ID == "" { return errors.New("cannot create document without both name and id") } if ones, err := g.ListCaseInsensitive(ctx, namespace, one.Name); err != nil { return err } else if len(ones) > 0 { return fmt.Errorf("collision on primary key when case insensitive: cannot create %q because %+v exists", one.Name, ones) } return g.driver.Insert(ctx, namespace, one) } func (g Graph) Update(ctx context.Context, namespace string, one, modify interface{}) error { return g.driver.Update(ctx, namespace, one, modify) } func (g Graph) Delete(ctx context.Context, namespace string, filter interface{}) error { return g.driver.Delete(ctx, namespace, filter) }