frostfs-node/pkg/services/object/search/query/v1/v1.go
Leonard Lyubich 16252ad09a [#58] object/search: Add object-with-children filter
Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2020-10-02 11:25:36 +03:00

118 lines
2.5 KiB
Go

package query
import (
"encoding/hex"
"fmt"
"github.com/nspcc-dev/neofs-api-go/pkg/container"
objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/services/object/search/query"
)
type Query struct {
filters []*Filter
}
type matchType uint8
type Filter struct {
matchType matchType
key, val string
}
const (
_ matchType = iota
matchStringEqual
)
func New(filters ...*Filter) query.Query {
return &Query{
filters: filters,
}
}
func idValue(id *objectSDK.ID) string {
return hex.EncodeToString(id.ToV2().GetValue())
}
func NewIDEqualFilter(id *objectSDK.ID) *Filter {
return NewFilterEqual(objectSDK.HdrSysNameID, idValue(id))
}
func cidValue(id *container.ID) string {
return hex.EncodeToString(id.ToV2().GetValue())
}
func NewContainerIDEqualFilter(id *container.ID) *Filter {
return NewFilterEqual(objectSDK.HdrSysNameCID, cidValue(id))
}
func ownerIDValue(id *owner.ID) string {
return hex.EncodeToString(id.ToV2().GetValue())
}
func NewOwnerIDEqualFilter(id *owner.ID) *Filter {
return NewFilterEqual(objectSDK.HdrSysNameOwnerID, ownerIDValue(id))
}
func NewFilterEqual(key, val string) *Filter {
return &Filter{
matchType: matchStringEqual,
key: key,
val: val,
}
}
func (q *Query) Match(obj *object.Object) bool {
for _, f := range q.filters {
switch f.matchType {
case matchStringEqual:
if !headerEqual(obj, f.key, f.val) {
return false
}
default:
panic(fmt.Sprintf("unsupported match type %d", f.matchType))
}
}
return true
}
func headerEqual(obj *object.Object, key, value string) bool {
switch key {
default:
for _, attr := range obj.GetAttributes() {
if attr.GetKey() == key && attr.GetValue() == value {
return true
}
}
return false
case objectSDK.HdrSysNameID:
return value == idValue(obj.GetID())
case objectSDK.HdrSysNameCID:
return value == cidValue(obj.GetContainerID())
case objectSDK.HdrSysNameOwnerID:
return value == ownerIDValue(obj.GetOwnerID())
case keyNoChildrenField:
return len(obj.GetChildren()) == 0
case keyParentIDField:
return idValue(obj.GetParent().GetID()) == value
case keyParentField:
return len(obj.GetChildren()) > 0
// TODO: add other headers
}
}
func (q *Query) ToSearchFilters() objectSDK.SearchFilters {
fs := make(objectSDK.SearchFilters, 0, len(q.filters))
for i := range q.filters {
fs.AddFilter(q.filters[i].key, q.filters[i].val, objectSDK.MatchStringEqual)
}
return fs
}