This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a commit to branch time-series
in repository https://gitbox.apache.org/repos/asf/skywalking-banyandb.git


The following commit(s) were added to refs/heads/time-series by this push:
     new 38d26c2  Add metadata module
38d26c2 is described below

commit 38d26c223f1e332f47a5ccce7236779b80d64d07
Author: Gao Hongtao <[email protected]>
AuthorDate: Tue Aug 24 22:43:26 2021 +0800

    Add metadata module
    
    Signed-off-by: Gao Hongtao <[email protected]>
---
 api/proto/banyandb/database/v2/schema.pb.go        | 282 +++++++++++++--------
 api/proto/banyandb/database/v2/schema.proto        |  25 +-
 banyand/metadata/metadata.go                       | 106 ++++++++
 banyand/metadata/metadata_test.go                  | 103 ++++++++
 .../metadata/schema/data/index_rule_binding.json   |  25 ++
 .../schema/data/index_rules/db.instance.json       |  12 +
 .../metadata/schema/data/index_rules/db.type.json  |  12 +
 .../metadata/schema/data/index_rules/duration.json |  12 +
 .../schema/data/index_rules/endpoint_id.json       |  12 +
 .../schema/data/index_rules/http.code.json         |  12 +
 .../schema/data/index_rules/http.method.json       |  12 +
 .../schema/data/index_rules/mq.broker.json         |  12 +
 .../metadata/schema/data/index_rules/mq.queue.json |  12 +
 .../metadata/schema/data/index_rules/mq.topic.json |  12 +
 .../metadata/schema/data/index_rules/trace_id.json |  12 +
 banyand/metadata/schema/data/stream.json           |  77 ++++++
 banyand/metadata/schema/schema.go                  |  44 ++++
 banyand/metadata/schema/sw.go                      | 124 +++++++++
 18 files changed, 790 insertions(+), 116 deletions(-)

diff --git a/api/proto/banyandb/database/v2/schema.pb.go 
b/api/proto/banyandb/database/v2/schema.pb.go
index c284b2b..3b623af 100644
--- a/api/proto/banyandb/database/v2/schema.pb.go
+++ b/api/proto/banyandb/database/v2/schema.pb.go
@@ -151,56 +151,105 @@ func (Duration_DurationUnit) EnumDescriptor() ([]byte, 
[]int) {
        return file_banyandb_database_v2_schema_proto_rawDescGZIP(), []int{0, 0}
 }
 
-// IndexType determine the index structure under the hood
-type IndexRule_IndexType int32
+// Type determine the index structure under the hood
+type IndexRule_Type int32
 
 const (
-       IndexRule_INDEX_TYPE_UNSPECIFIED    IndexRule_IndexType = 0
-       IndexRule_INDEX_TYPE_BLOCK_ATTACHED IndexRule_IndexType = 1
-       IndexRule_INDEX_TYPE_TRACE          IndexRule_IndexType = 2
+       IndexRule_TYPE_UNSPECIFIED IndexRule_Type = 0
+       IndexRule_TYPE_TREE        IndexRule_Type = 1
+       IndexRule_TYPE_INVERTED    IndexRule_Type = 2
 )
 
-// Enum value maps for IndexRule_IndexType.
+// Enum value maps for IndexRule_Type.
 var (
-       IndexRule_IndexType_name = map[int32]string{
-               0: "INDEX_TYPE_UNSPECIFIED",
-               1: "INDEX_TYPE_BLOCK_ATTACHED",
-               2: "INDEX_TYPE_TRACE",
+       IndexRule_Type_name = map[int32]string{
+               0: "TYPE_UNSPECIFIED",
+               1: "TYPE_TREE",
+               2: "TYPE_INVERTED",
        }
-       IndexRule_IndexType_value = map[string]int32{
-               "INDEX_TYPE_UNSPECIFIED":    0,
-               "INDEX_TYPE_BLOCK_ATTACHED": 1,
-               "INDEX_TYPE_TRACE":          2,
+       IndexRule_Type_value = map[string]int32{
+               "TYPE_UNSPECIFIED": 0,
+               "TYPE_TREE":        1,
+               "TYPE_INVERTED":    2,
        }
 )
 
-func (x IndexRule_IndexType) Enum() *IndexRule_IndexType {
-       p := new(IndexRule_IndexType)
+func (x IndexRule_Type) Enum() *IndexRule_Type {
+       p := new(IndexRule_Type)
        *p = x
        return p
 }
 
-func (x IndexRule_IndexType) String() string {
+func (x IndexRule_Type) String() string {
        return protoimpl.X.EnumStringOf(x.Descriptor(), 
protoreflect.EnumNumber(x))
 }
 
-func (IndexRule_IndexType) Descriptor() protoreflect.EnumDescriptor {
+func (IndexRule_Type) Descriptor() protoreflect.EnumDescriptor {
        return file_banyandb_database_v2_schema_proto_enumTypes[2].Descriptor()
 }
 
-func (IndexRule_IndexType) Type() protoreflect.EnumType {
+func (IndexRule_Type) Type() protoreflect.EnumType {
        return &file_banyandb_database_v2_schema_proto_enumTypes[2]
 }
 
-func (x IndexRule_IndexType) Number() protoreflect.EnumNumber {
+func (x IndexRule_Type) Number() protoreflect.EnumNumber {
        return protoreflect.EnumNumber(x)
 }
 
-// Deprecated: Use IndexRule_IndexType.Descriptor instead.
-func (IndexRule_IndexType) EnumDescriptor() ([]byte, []int) {
+// Deprecated: Use IndexRule_Type.Descriptor instead.
+func (IndexRule_Type) EnumDescriptor() ([]byte, []int) {
        return file_banyandb_database_v2_schema_proto_rawDescGZIP(), []int{4, 0}
 }
 
+type IndexRule_Location int32
+
+const (
+       IndexRule_LOCATION_UNSPECIFIED    IndexRule_Location = 0
+       IndexRule_LOCATION_ATTACHED_BLOCK IndexRule_Location = 1
+       IndexRule_LOCATION_AGGREGATION    IndexRule_Location = 2
+)
+
+// Enum value maps for IndexRule_Location.
+var (
+       IndexRule_Location_name = map[int32]string{
+               0: "LOCATION_UNSPECIFIED",
+               1: "LOCATION_ATTACHED_BLOCK",
+               2: "LOCATION_AGGREGATION",
+       }
+       IndexRule_Location_value = map[string]int32{
+               "LOCATION_UNSPECIFIED":    0,
+               "LOCATION_ATTACHED_BLOCK": 1,
+               "LOCATION_AGGREGATION":    2,
+       }
+)
+
+func (x IndexRule_Location) Enum() *IndexRule_Location {
+       p := new(IndexRule_Location)
+       *p = x
+       return p
+}
+
+func (x IndexRule_Location) String() string {
+       return protoimpl.X.EnumStringOf(x.Descriptor(), 
protoreflect.EnumNumber(x))
+}
+
+func (IndexRule_Location) Descriptor() protoreflect.EnumDescriptor {
+       return file_banyandb_database_v2_schema_proto_enumTypes[3].Descriptor()
+}
+
+func (IndexRule_Location) Type() protoreflect.EnumType {
+       return &file_banyandb_database_v2_schema_proto_enumTypes[3]
+}
+
+func (x IndexRule_Location) Number() protoreflect.EnumNumber {
+       return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use IndexRule_Location.Descriptor instead.
+func (IndexRule_Location) EnumDescriptor() ([]byte, []int) {
+       return file_banyandb_database_v2_schema_proto_rawDescGZIP(), []int{4, 1}
+}
+
 // Duration represents the elapsed time between two instants
 type Duration struct {
        state         protoimpl.MessageState
@@ -466,9 +515,11 @@ type IndexRule struct {
        // Caveat: All tags in a multi-tag MUST have an identical IndexType
        Tags []string `protobuf:"bytes,2,rep,name=tags,proto3" 
json:"tags,omitempty"`
        // type is the IndexType of this IndexObject.
-       Type IndexRule_IndexType 
`protobuf:"varint,3,opt,name=type,proto3,enum=banyandb.database.v2.IndexRule_IndexType"
 json:"type,omitempty"`
+       Type IndexRule_Type 
`protobuf:"varint,3,opt,name=type,proto3,enum=banyandb.database.v2.IndexRule_Type"
 json:"type,omitempty"`
+       // location indicates where to store index.
+       Location IndexRule_Location 
`protobuf:"varint,4,opt,name=location,proto3,enum=banyandb.database.v2.IndexRule_Location"
 json:"location,omitempty"`
        // updated_at_nanoseconds indicates when the IndexRule is updated
-       UpdatedAt *timestamppb.Timestamp 
`protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" 
json:"updated_at,omitempty"`
+       UpdatedAt *timestamppb.Timestamp 
`protobuf:"bytes,5,opt,name=updated_at,json=updatedAt,proto3" 
json:"updated_at,omitempty"`
 }
 
 func (x *IndexRule) Reset() {
@@ -517,11 +568,18 @@ func (x *IndexRule) GetTags() []string {
        return nil
 }
 
-func (x *IndexRule) GetType() IndexRule_IndexType {
+func (x *IndexRule) GetType() IndexRule_Type {
        if x != nil {
                return x.Type
        }
-       return IndexRule_INDEX_TYPE_UNSPECIFIED
+       return IndexRule_TYPE_UNSPECIFIED
+}
+
+func (x *IndexRule) GetLocation() IndexRule_Location {
+       if x != nil {
+               return x.Location
+       }
+       return IndexRule_LOCATION_UNSPECIFIED
 }
 
 func (x *IndexRule) GetUpdatedAt() *timestamppb.Timestamp {
@@ -601,8 +659,8 @@ type IndexRuleBinding struct {
        Metadata *v2.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" 
json:"metadata,omitempty"`
        // rules refers to the IndexRule
        Rules []string `protobuf:"bytes,2,rep,name=rules,proto3" 
json:"rules,omitempty"`
-       // subjects indicate the subjects of binding action
-       Subjects *Subject `protobuf:"bytes,3,opt,name=subjects,proto3" 
json:"subjects,omitempty"`
+       // subject indicates the subject of binding action
+       Subject *Subject `protobuf:"bytes,3,opt,name=subject,proto3" 
json:"subject,omitempty"`
        // begin_at_nanoseconds is the timestamp, after which the binding will 
be active
        BeginAt *timestamppb.Timestamp 
`protobuf:"bytes,4,opt,name=begin_at,json=beginAt,proto3" 
json:"begin_at,omitempty"`
        // expire_at_nanoseconds it the timestamp, after which the binding will 
be inactive
@@ -658,9 +716,9 @@ func (x *IndexRuleBinding) GetRules() []string {
        return nil
 }
 
-func (x *IndexRuleBinding) GetSubjects() *Subject {
+func (x *IndexRuleBinding) GetSubject() *Subject {
        if x != nil {
-               return x.Subjects
+               return x.Subject
        }
        return nil
 }
@@ -739,68 +797,76 @@ var file_banyandb_database_v2_schema_proto_rawDesc = 
[]byte{
        0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 
0x64, 0x41, 0x74, 0x22,
        0x25, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1b, 0x0a, 
0x09, 0x74, 0x61, 0x67,
        0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 
0x52, 0x08, 0x74, 0x61,
-       0x67, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xb1, 0x02, 0x0a, 0x09, 0x49, 
0x6e, 0x64, 0x65, 0x78,
+       0x67, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0xb1, 0x03, 0x0a, 0x09, 0x49, 
0x6e, 0x64, 0x65, 0x78,
        0x52, 0x75, 0x6c, 0x65, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 
0x64, 0x61, 0x74, 0x61,
        0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 
0x79, 0x61, 0x6e, 0x64,
        0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x32, 0x2e, 
0x4d, 0x65, 0x74, 0x61,
        0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 
0x74, 0x61, 0x12, 0x12,
        0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 
0x52, 0x04, 0x74, 0x61,
-       0x67, 0x73, 0x12, 0x3d, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 
0x20, 0x01, 0x28, 0x0e,
-       0x32, 0x29, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 
0x64, 0x61, 0x74, 0x61,
+       0x67, 0x73, 0x12, 0x38, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 
0x20, 0x01, 0x28, 0x0e,
+       0x32, 0x24, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 
0x64, 0x61, 0x74, 0x61,
        0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6e, 0x64, 0x65, 
0x78, 0x52, 0x75, 0x6c,
-       0x65, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, 
0x04, 0x74, 0x79, 0x70,
-       0x65, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 
0x5f, 0x61, 0x74, 0x18,
-       0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 
0x6c, 0x65, 0x2e, 0x70,
-       0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 
0x73, 0x74, 0x61, 0x6d,
-       0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 
0x22, 0x5c, 0x0a, 0x09,
-       0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 
0x16, 0x49, 0x4e, 0x44,
-       0x45, 0x58, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 
0x45, 0x43, 0x49, 0x46,
-       0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1d, 0x0a, 0x19, 0x49, 0x4e, 0x44, 
0x45, 0x58, 0x5f, 0x54,
-       0x59, 0x50, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x41, 0x54, 
0x54, 0x41, 0x43, 0x48,
-       0x45, 0x44, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, 0x44, 0x45, 
0x58, 0x5f, 0x54, 0x59,
-       0x50, 0x45, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x02, 0x22, 0x54, 
0x0a, 0x07, 0x53, 0x75,
+       0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 
0x12, 0x44, 0x0a, 0x08,
+       0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 
0x28, 0x0e, 0x32, 0x28,
+       0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61, 
0x74, 0x61, 0x62, 0x61,
+       0x73, 0x65, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 
0x75, 0x6c, 0x65, 0x2e,
+       0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 
0x63, 0x61, 0x74, 0x69,
+       0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 
0x64, 0x5f, 0x61, 0x74,
+       0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 
0x67, 0x6c, 0x65, 0x2e,
+       0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 
0x65, 0x73, 0x74, 0x61,
+       0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 
0x74, 0x22, 0x3e, 0x0a,
+       0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 
0x45, 0x5f, 0x55, 0x4e,
+       0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 
0x0d, 0x0a, 0x09, 0x54,
+       0x59, 0x50, 0x45, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x01, 0x12, 0x11, 
0x0a, 0x0d, 0x54, 0x59,
+       0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x45, 0x52, 0x54, 0x45, 0x44, 0x10, 
0x02, 0x22, 0x5b, 0x0a,
+       0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 
0x14, 0x4c, 0x4f, 0x43,
+       0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 
0x49, 0x46, 0x49, 0x45,
+       0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x4f, 0x43, 0x41, 0x54, 
0x49, 0x4f, 0x4e, 0x5f,
+       0x41, 0x54, 0x54, 0x41, 0x43, 0x48, 0x45, 0x44, 0x5f, 0x42, 0x4c, 0x4f, 
0x43, 0x4b, 0x10, 0x01,
+       0x12, 0x18, 0x0a, 0x14, 0x4c, 0x4f, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 
0x5f, 0x41, 0x47, 0x47,
+       0x52, 0x45, 0x47, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x22, 0x54, 
0x0a, 0x07, 0x53, 0x75,
        0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x07, 0x63, 0x61, 0x74, 
0x61, 0x6c, 0x6f, 0x67,
        0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 
0x79, 0x61, 0x6e, 0x64,
        0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x32, 0x2e, 
0x43, 0x61, 0x74, 0x61,
        0x6c, 0x6f, 0x67, 0x52, 0x07, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 
0x12, 0x12, 0x0a, 0x04,
        0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 
0x6e, 0x61, 0x6d, 0x65,
-       0x22, 0xc8, 0x02, 0x0a, 0x10, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x75, 
0x6c, 0x65, 0x42, 0x69,
+       0x22, 0xc6, 0x02, 0x0a, 0x10, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x75, 
0x6c, 0x65, 0x42, 0x69,
        0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 
0x61, 0x64, 0x61, 0x74,
        0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 
0x6e, 0x79, 0x61, 0x6e,
        0x64, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x32, 
0x2e, 0x4d, 0x65, 0x74,
        0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 
0x61, 0x74, 0x61, 0x12,
        0x14, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 
0x28, 0x09, 0x52, 0x05,
-       0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x08, 0x73, 0x75, 0x62, 
0x6a, 0x65, 0x63, 0x74,
-       0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x61, 
0x6e, 0x79, 0x61, 0x6e,
-       0x64, 0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 
0x76, 0x32, 0x2e, 0x53,
-       0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6a, 
0x65, 0x63, 0x74, 0x73,
-       0x12, 0x35, 0x0a, 0x08, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x61, 0x74, 
0x18, 0x04, 0x20, 0x01,
+       0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x62, 
0x6a, 0x65, 0x63, 0x74,
+       0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x61, 0x6e, 
0x79, 0x61, 0x6e, 0x64,
+       0x62, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 
0x32, 0x2e, 0x53, 0x75,
+       0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 
0x63, 0x74, 0x12, 0x35,
+       0x0a, 0x08, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x61, 0x74, 0x18, 0x04, 
0x20, 0x01, 0x28, 0x0b,
+       0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 
0x6f, 0x74, 0x6f, 0x62,
+       0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 
0x52, 0x07, 0x62, 0x65,
+       0x67, 0x69, 0x6e, 0x41, 0x74, 0x12, 0x37, 0x0a, 0x09, 0x65, 0x78, 0x70, 
0x69, 0x72, 0x65, 0x5f,
+       0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 
0x6f, 0x6f, 0x67, 0x6c,
+       0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 
0x69, 0x6d, 0x65, 0x73,
+       0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 
0x41, 0x74, 0x12, 0x39,
+       0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 
0x18, 0x06, 0x20, 0x01,
        0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 
0x70, 0x72, 0x6f, 0x74,
-       0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 
0x6d, 0x70, 0x52, 0x07,
-       0x62, 0x65, 0x67, 0x69, 0x6e, 0x41, 0x74, 0x12, 0x37, 0x0a, 0x09, 0x65, 
0x78, 0x70, 0x69, 0x72,
-       0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 
0x2e, 0x67, 0x6f, 0x6f,
-       0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 
0x2e, 0x54, 0x69, 0x6d,
-       0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 
0x72, 0x65, 0x41, 0x74,
-       0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 
0x61, 0x74, 0x18, 0x06,
-       0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 
0x65, 0x2e, 0x70, 0x72,
-       0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 
0x74, 0x61, 0x6d, 0x70,
-       0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x2a, 
0x7d, 0x0a, 0x07, 0x54,
-       0x61, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x41, 
0x47, 0x5f, 0x54, 0x59,
-       0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 
0x45, 0x44, 0x10, 0x00,
-       0x12, 0x13, 0x0a, 0x0f, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 
0x5f, 0x53, 0x54, 0x52,
-       0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x41, 0x47, 
0x5f, 0x54, 0x59, 0x50,
-       0x45, 0x5f, 0x49, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x54, 
0x41, 0x47, 0x5f, 0x54,
-       0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x41, 
0x52, 0x52, 0x41, 0x59,
-       0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 
0x50, 0x45, 0x5f, 0x49,
-       0x4e, 0x54, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x10, 0x04, 0x42, 0x72, 
0x0a, 0x2a, 0x6f, 0x72,
-       0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x6b, 0x79, 
0x77, 0x61, 0x6c, 0x6b,
-       0x69, 0x6e, 0x67, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 
0x2e, 0x64, 0x61, 0x74,
-       0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x32, 0x5a, 0x44, 0x67, 0x69, 
0x74, 0x68, 0x75, 0x62,
-       0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 
0x73, 0x6b, 0x79, 0x77,
-       0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x61, 0x6e, 0x79, 0x61, 
0x6e, 0x64, 0x62, 0x2f,
-       0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x61, 
0x6e, 0x79, 0x61, 0x6e,
-       0x64, 0x62, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 
0x76, 0x32, 0x62, 0x06,
-       0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+       0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 
0x6d, 0x70, 0x52, 0x09,
+       0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x2a, 0x7d, 0x0a, 
0x07, 0x54, 0x61, 0x67,
+       0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x41, 0x47, 0x5f, 
0x54, 0x59, 0x50, 0x45,
+       0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 
0x10, 0x00, 0x12, 0x13,
+       0x0a, 0x0f, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 
0x54, 0x52, 0x49, 0x4e,
+       0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x41, 0x47, 0x5f, 0x54, 
0x59, 0x50, 0x45, 0x5f,
+       0x49, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x41, 0x47, 
0x5f, 0x54, 0x59, 0x50,
+       0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x41, 0x52, 0x52, 
0x41, 0x59, 0x10, 0x03,
+       0x12, 0x16, 0x0a, 0x12, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 
0x5f, 0x49, 0x4e, 0x54,
+       0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x10, 0x04, 0x42, 0x72, 0x0a, 0x2a, 
0x6f, 0x72, 0x67, 0x2e,
+       0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x6b, 0x79, 0x77, 0x61, 
0x6c, 0x6b, 0x69, 0x6e,
+       0x67, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 
0x61, 0x74, 0x61, 0x62,
+       0x61, 0x73, 0x65, 0x2e, 0x76, 0x32, 0x5a, 0x44, 0x67, 0x69, 0x74, 0x68, 
0x75, 0x62, 0x2e, 0x63,
+       0x6f, 0x6d, 0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x73, 0x6b, 
0x79, 0x77, 0x61, 0x6c,
+       0x6b, 0x69, 0x6e, 0x67, 0x2d, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 
0x62, 0x2f, 0x61, 0x70,
+       0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x62, 0x61, 0x6e, 0x79, 
0x61, 0x6e, 0x64, 0x62,
+       0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x32, 
0x62, 0x06, 0x70, 0x72,
+       0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -815,45 +881,47 @@ func file_banyandb_database_v2_schema_proto_rawDescGZIP() 
[]byte {
        return file_banyandb_database_v2_schema_proto_rawDescData
 }
 
-var file_banyandb_database_v2_schema_proto_enumTypes = 
make([]protoimpl.EnumInfo, 3)
+var file_banyandb_database_v2_schema_proto_enumTypes = 
make([]protoimpl.EnumInfo, 4)
 var file_banyandb_database_v2_schema_proto_msgTypes = 
make([]protoimpl.MessageInfo, 7)
 var file_banyandb_database_v2_schema_proto_goTypes = []interface{}{
        (TagType)(0),                  // 0: banyandb.database.v2.TagType
        (Duration_DurationUnit)(0),    // 1: 
banyandb.database.v2.Duration.DurationUnit
-       (IndexRule_IndexType)(0),      // 2: 
banyandb.database.v2.IndexRule.IndexType
-       (*Duration)(nil),              // 3: banyandb.database.v2.Duration
-       (*TagSpec)(nil),               // 4: banyandb.database.v2.TagSpec
-       (*Stream)(nil),                // 5: banyandb.database.v2.Stream
-       (*Entity)(nil),                // 6: banyandb.database.v2.Entity
-       (*IndexRule)(nil),             // 7: banyandb.database.v2.IndexRule
-       (*Subject)(nil),               // 8: banyandb.database.v2.Subject
-       (*IndexRuleBinding)(nil),      // 9: 
banyandb.database.v2.IndexRuleBinding
-       (*v2.Metadata)(nil),           // 10: banyandb.common.v2.Metadata
-       (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp
-       (v2.Catalog)(0),               // 12: banyandb.common.v2.Catalog
+       (IndexRule_Type)(0),           // 2: banyandb.database.v2.IndexRule.Type
+       (IndexRule_Location)(0),       // 3: 
banyandb.database.v2.IndexRule.Location
+       (*Duration)(nil),              // 4: banyandb.database.v2.Duration
+       (*TagSpec)(nil),               // 5: banyandb.database.v2.TagSpec
+       (*Stream)(nil),                // 6: banyandb.database.v2.Stream
+       (*Entity)(nil),                // 7: banyandb.database.v2.Entity
+       (*IndexRule)(nil),             // 8: banyandb.database.v2.IndexRule
+       (*Subject)(nil),               // 9: banyandb.database.v2.Subject
+       (*IndexRuleBinding)(nil),      // 10: 
banyandb.database.v2.IndexRuleBinding
+       (*v2.Metadata)(nil),           // 11: banyandb.common.v2.Metadata
+       (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp
+       (v2.Catalog)(0),               // 13: banyandb.common.v2.Catalog
 }
 var file_banyandb_database_v2_schema_proto_depIdxs = []int32{
        1,  // 0: banyandb.database.v2.Duration.unit:type_name -> 
banyandb.database.v2.Duration.DurationUnit
        0,  // 1: banyandb.database.v2.TagSpec.type:type_name -> 
banyandb.database.v2.TagType
-       10, // 2: banyandb.database.v2.Stream.metadata:type_name -> 
banyandb.common.v2.Metadata
-       4,  // 3: banyandb.database.v2.Stream.tags:type_name -> 
banyandb.database.v2.TagSpec
-       6,  // 4: banyandb.database.v2.Stream.entity:type_name -> 
banyandb.database.v2.Entity
-       3,  // 5: banyandb.database.v2.Stream.duration:type_name -> 
banyandb.database.v2.Duration
-       11, // 6: banyandb.database.v2.Stream.updated_at:type_name -> 
google.protobuf.Timestamp
-       10, // 7: banyandb.database.v2.IndexRule.metadata:type_name -> 
banyandb.common.v2.Metadata
-       2,  // 8: banyandb.database.v2.IndexRule.type:type_name -> 
banyandb.database.v2.IndexRule.IndexType
-       11, // 9: banyandb.database.v2.IndexRule.updated_at:type_name -> 
google.protobuf.Timestamp
-       12, // 10: banyandb.database.v2.Subject.catalog:type_name -> 
banyandb.common.v2.Catalog
-       10, // 11: banyandb.database.v2.IndexRuleBinding.metadata:type_name -> 
banyandb.common.v2.Metadata
-       8,  // 12: banyandb.database.v2.IndexRuleBinding.subjects:type_name -> 
banyandb.database.v2.Subject
-       11, // 13: banyandb.database.v2.IndexRuleBinding.begin_at:type_name -> 
google.protobuf.Timestamp
-       11, // 14: banyandb.database.v2.IndexRuleBinding.expire_at:type_name -> 
google.protobuf.Timestamp
-       11, // 15: banyandb.database.v2.IndexRuleBinding.updated_at:type_name 
-> google.protobuf.Timestamp
-       16, // [16:16] is the sub-list for method output_type
-       16, // [16:16] is the sub-list for method input_type
-       16, // [16:16] is the sub-list for extension type_name
-       16, // [16:16] is the sub-list for extension extendee
-       0,  // [0:16] is the sub-list for field type_name
+       11, // 2: banyandb.database.v2.Stream.metadata:type_name -> 
banyandb.common.v2.Metadata
+       5,  // 3: banyandb.database.v2.Stream.tags:type_name -> 
banyandb.database.v2.TagSpec
+       7,  // 4: banyandb.database.v2.Stream.entity:type_name -> 
banyandb.database.v2.Entity
+       4,  // 5: banyandb.database.v2.Stream.duration:type_name -> 
banyandb.database.v2.Duration
+       12, // 6: banyandb.database.v2.Stream.updated_at:type_name -> 
google.protobuf.Timestamp
+       11, // 7: banyandb.database.v2.IndexRule.metadata:type_name -> 
banyandb.common.v2.Metadata
+       2,  // 8: banyandb.database.v2.IndexRule.type:type_name -> 
banyandb.database.v2.IndexRule.Type
+       3,  // 9: banyandb.database.v2.IndexRule.location:type_name -> 
banyandb.database.v2.IndexRule.Location
+       12, // 10: banyandb.database.v2.IndexRule.updated_at:type_name -> 
google.protobuf.Timestamp
+       13, // 11: banyandb.database.v2.Subject.catalog:type_name -> 
banyandb.common.v2.Catalog
+       11, // 12: banyandb.database.v2.IndexRuleBinding.metadata:type_name -> 
banyandb.common.v2.Metadata
+       9,  // 13: banyandb.database.v2.IndexRuleBinding.subject:type_name -> 
banyandb.database.v2.Subject
+       12, // 14: banyandb.database.v2.IndexRuleBinding.begin_at:type_name -> 
google.protobuf.Timestamp
+       12, // 15: banyandb.database.v2.IndexRuleBinding.expire_at:type_name -> 
google.protobuf.Timestamp
+       12, // 16: banyandb.database.v2.IndexRuleBinding.updated_at:type_name 
-> google.protobuf.Timestamp
+       17, // [17:17] is the sub-list for method output_type
+       17, // [17:17] is the sub-list for method input_type
+       17, // [17:17] is the sub-list for extension type_name
+       17, // [17:17] is the sub-list for extension extendee
+       0,  // [0:17] is the sub-list for field type_name
 }
 
 func init() { file_banyandb_database_v2_schema_proto_init() }
@@ -952,7 +1020,7 @@ func file_banyandb_database_v2_schema_proto_init() {
                File: protoimpl.DescBuilder{
                        GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
                        RawDescriptor: 
file_banyandb_database_v2_schema_proto_rawDesc,
-                       NumEnums:      3,
+                       NumEnums:      4,
                        NumMessages:   7,
                        NumExtensions: 0,
                        NumServices:   0,
diff --git a/api/proto/banyandb/database/v2/schema.proto 
b/api/proto/banyandb/database/v2/schema.proto
index e0ffed7..2ef8f25 100644
--- a/api/proto/banyandb/database/v2/schema.proto
+++ b/api/proto/banyandb/database/v2/schema.proto
@@ -79,16 +79,23 @@ message IndexRule {
     // If the elements in tags are more than 1, the object will generate a 
multi-tag index
     // Caveat: All tags in a multi-tag MUST have an identical IndexType
     repeated string tags = 2;
-    // IndexType determine the index structure under the hood
-    enum IndexType {
-        INDEX_TYPE_UNSPECIFIED = 0;
-        INDEX_TYPE_BLOCK_ATTACHED = 1;
-        INDEX_TYPE_TRACE = 2;
+    // Type determine the index structure under the hood
+    enum Type {
+        TYPE_UNSPECIFIED = 0;
+        TYPE_TREE = 1;
+        TYPE_INVERTED = 2;
     }
     // type is the IndexType of this IndexObject.
-    IndexType type = 3;
+    Type type = 3;
+    enum Location {
+        LOCATION_UNSPECIFIED = 0;
+        LOCATION_ATTACHED_BLOCK = 1;
+        LOCATION_AGGREGATION = 2;
+    }
+    // location indicates where to store index.
+    Location location = 4;
     // updated_at_nanoseconds indicates when the IndexRule is updated
-    google.protobuf.Timestamp updated_at = 6;
+    google.protobuf.Timestamp updated_at = 5;
 }
 
 // Subject defines which stream or measure would generate indices
@@ -107,8 +114,8 @@ message IndexRuleBinding {
     common.v2.Metadata metadata = 1;
     // rules refers to the IndexRule
     repeated string rules = 2;
-    // subjects indicate the subjects of binding action
-    Subject subjects = 3;
+    // subject indicates the subject of binding action
+    Subject subject = 3;
     // begin_at_nanoseconds is the timestamp, after which the binding will be 
active
     google.protobuf.Timestamp begin_at = 4;
     // expire_at_nanoseconds it the timestamp, after which the binding will be 
inactive
diff --git a/banyand/metadata/metadata.go b/banyand/metadata/metadata.go
new file mode 100644
index 0000000..57e1fd9
--- /dev/null
+++ b/banyand/metadata/metadata.go
@@ -0,0 +1,106 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package metadata
+
+import (
+       "context"
+       "time"
+
+       "go.uber.org/multierr"
+
+       commonv2 
"github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v2"
+       databasev2 
"github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
+       "github.com/apache/skywalking-banyandb/banyand/metadata/schema"
+       "github.com/apache/skywalking-banyandb/pkg/run"
+)
+
+//IndexFilter provides methods to find a specific index related objects
+type IndexFilter interface {
+       //IndexRules fetches v2.IndexRule by subject defined in IndexRuleBinding
+       IndexRules(ctx context.Context, subject *commonv2.Metadata) 
([]*databasev2.IndexRule, error)
+}
+
+type Metadata interface {
+       IndexFilter
+       run.Unit
+}
+
+type service struct {
+       stream           schema.Stream
+       indexRule        schema.IndexRule
+       indexRuleBinding schema.IndexRuleBinding
+}
+
+func (s *service) Name() string {
+       return "metadata"
+}
+
+func NewService(_ context.Context) (Metadata, error) {
+       stream, err := schema.NewStream()
+       if err != nil {
+               return nil, err
+       }
+       indexRule, err := schema.NewIndexRule()
+       if err != nil {
+               return nil, err
+       }
+       indexRuleBinding, err := schema.NewIndexRuleBinding()
+       if err != nil {
+               return nil, err
+       }
+       return &service{
+               stream:           stream,
+               indexRule:        indexRule,
+               indexRuleBinding: indexRuleBinding,
+       }, nil
+}
+
+func (s *service) IndexRules(ctx context.Context, subject *commonv2.Metadata) 
([]*databasev2.IndexRule, error) {
+       bindings, err := s.indexRuleBinding.List(ctx, schema.ListOpt{Group: 
subject.Group})
+       if err != nil {
+               return nil, err
+       }
+       now := time.Now()
+       foundRules := make([]string, 0)
+       for _, binding := range bindings {
+               if binding.GetBeginAt().AsTime().After(now) ||
+                       binding.GetExpireAt().AsTime().Before(now) {
+                       continue
+               }
+               sub := binding.GetSubject()
+               if sub.Name != subject.Name {
+                       continue
+               }
+               foundRules = append(foundRules, binding.Rules...)
+       }
+       result := make([]*databasev2.IndexRule, 0, len(foundRules))
+       var indexRuleErr error
+       for _, rule := range foundRules {
+               r, getErr := s.indexRule.Get(ctx, &commonv2.Metadata{
+                       Name:  rule,
+                       Group: subject.Group,
+               })
+               if getErr != nil {
+                       indexRuleErr = multierr.Append(indexRuleErr, err)
+                       continue
+               }
+               result = append(result, r)
+
+       }
+       return result, indexRuleErr
+}
diff --git a/banyand/metadata/metadata_test.go 
b/banyand/metadata/metadata_test.go
new file mode 100644
index 0000000..9264542
--- /dev/null
+++ b/banyand/metadata/metadata_test.go
@@ -0,0 +1,103 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package metadata
+
+import (
+       "context"
+       "testing"
+
+       "github.com/stretchr/testify/assert"
+
+       commonv2 
"github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v2"
+       databasev2 
"github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
+       "github.com/apache/skywalking-banyandb/banyand/metadata/schema"
+)
+
+func Test_service_RulesBySubject(t *testing.T) {
+       type args struct {
+               subject *commonv2.Metadata
+       }
+       is := assert.New(t)
+       tests := []struct {
+               name    string
+               args    args
+               want    []*databasev2.IndexRule
+               wantErr bool
+       }{
+               {
+                       name: "golden path",
+                       args: args{
+                               subject: createSubject("sw", "default"),
+                       },
+                       want: getIndexRule(
+                               "trace_id",
+                               "duration",
+                               "endpoint_id",
+                               "http.code",
+                               "http.method",
+                               "db.instance",
+                               "db.type",
+                               "mq.broker",
+                               "mq.queue",
+                               "mq.topic"),
+               },
+               {
+                       name: "got empty idWithShard",
+                       args: args{
+                               subject: createSubject("invalid", "default"),
+                       },
+                       want: make([]*databasev2.IndexRule, 0),
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       ctx := context.TODO()
+                       s, err := NewService(ctx)
+                       if (err != nil) != tt.wantErr {
+                               t.Errorf("NewService() error = %v, wantErr %v", 
err, tt.wantErr)
+                               return
+                       }
+                       got, err := s.IndexRules(ctx, tt.args.subject)
+                       if (err != nil) != tt.wantErr {
+                               t.Errorf("RulesBySubject() error = %v, wantErr 
%v", err, tt.wantErr)
+                               return
+                       }
+                       is.Equal(tt.want, got)
+               })
+       }
+}
+
+func getIndexRule(names ...string) []*databasev2.IndexRule {
+       ruleRepo, _ := schema.NewIndexRule()
+       result := make([]*databasev2.IndexRule, 0, len(names))
+       for _, name := range names {
+               indexRule, _ := ruleRepo.Get(context.TODO(), &commonv2.Metadata{
+                       Group: "default",
+                       Name:  name,
+               })
+               result = append(result, indexRule)
+       }
+       return result
+}
+
+func createSubject(name, group string) *commonv2.Metadata {
+       return &commonv2.Metadata{
+               Group: group,
+               Name:  name,
+       }
+}
diff --git a/banyand/metadata/schema/data/index_rule_binding.json 
b/banyand/metadata/schema/data/index_rule_binding.json
new file mode 100644
index 0000000..82a7f1c
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rule_binding.json
@@ -0,0 +1,25 @@
+{
+  "metadata": {
+    "name": "sw-index-rule-binding",
+    "group": "default"
+  },
+  "rules": [
+    "trace_id",
+    "duration",
+    "endpoint_id",
+    "http.code",
+    "http.method",
+    "db.instance",
+    "db.type",
+    "mq.broker",
+    "mq.queue",
+    "mq.topic"
+  ],
+  "subject":{
+    "catalog": "CATALOG_STREAM",
+    "name": "sw"
+  },
+  "begin_at": "2021-04-15T01:30:15.01Z",
+  "expire_at": "2121-04-15T01:30:15.01Z",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/db.instance.json 
b/banyand/metadata/schema/data/index_rules/db.instance.json
new file mode 100644
index 0000000..e35f3a6
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/db.instance.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "db.instance",
+    "group": "default"
+  },
+  "tags": [
+    "db.instance"
+  ],
+  "type": "TYPE_INVERTED",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/db.type.json 
b/banyand/metadata/schema/data/index_rules/db.type.json
new file mode 100644
index 0000000..015522c
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/db.type.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "db.type",
+    "group": "default"
+  },
+  "tags": [
+    "db.type"
+  ],
+  "type": "TYPE_INVERTED",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/duration.json 
b/banyand/metadata/schema/data/index_rules/duration.json
new file mode 100644
index 0000000..7cc8180
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/duration.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "duration",
+    "group": "default"
+  },
+  "tags": [
+    "duration"
+  ],
+  "type": "TYPE_TREE",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/endpoint_id.json 
b/banyand/metadata/schema/data/index_rules/endpoint_id.json
new file mode 100644
index 0000000..248a29c
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/endpoint_id.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "endpoint_id",
+    "group": "default"
+  },
+  "tags": [
+    "endpoint_id"
+  ],
+  "type": "TYPE_INVERTED",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/http.code.json 
b/banyand/metadata/schema/data/index_rules/http.code.json
new file mode 100644
index 0000000..6b5c757
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/http.code.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "http.code",
+    "group": "default"
+  },
+  "tags": [
+    "http.code"
+  ],
+  "type": "TYPE_INVERTED",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/http.method.json 
b/banyand/metadata/schema/data/index_rules/http.method.json
new file mode 100644
index 0000000..7619604
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/http.method.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "http.method",
+    "group": "default"
+  },
+  "tags": [
+    "http.method"
+  ],
+  "type": "TYPE_INVERTED",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/mq.broker.json 
b/banyand/metadata/schema/data/index_rules/mq.broker.json
new file mode 100644
index 0000000..9d2bd6a
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/mq.broker.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "mq.broker",
+    "group": "default"
+  },
+  "tags": [
+    "mq.broker"
+  ],
+  "type": "TYPE_INVERTED",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/mq.queue.json 
b/banyand/metadata/schema/data/index_rules/mq.queue.json
new file mode 100644
index 0000000..ccf9a3c
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/mq.queue.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "mq.queue",
+    "group": "default"
+  },
+  "tags": [
+    "mq.queue"
+  ],
+  "type": "TYPE_INVERTED",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/mq.topic.json 
b/banyand/metadata/schema/data/index_rules/mq.topic.json
new file mode 100644
index 0000000..5255e5b
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/mq.topic.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "mq.topic",
+    "group": "default"
+  },
+  "tags": [
+    "mq.topic"
+  ],
+  "type": "TYPE_INVERTED",
+  "location": "LOCATION_ATTACHED_BLOCK",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/index_rules/trace_id.json 
b/banyand/metadata/schema/data/index_rules/trace_id.json
new file mode 100644
index 0000000..5061326
--- /dev/null
+++ b/banyand/metadata/schema/data/index_rules/trace_id.json
@@ -0,0 +1,12 @@
+{
+  "metadata": {
+    "name": "trace_id",
+    "group": "default"
+  },
+  "tags": [
+    "trace_id"
+  ],
+  "type": "TYPE_TREE",
+  "location": "LOCATION_AGGREGATION",
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
diff --git a/banyand/metadata/schema/data/stream.json 
b/banyand/metadata/schema/data/stream.json
new file mode 100644
index 0000000..5dfefec
--- /dev/null
+++ b/banyand/metadata/schema/data/stream.json
@@ -0,0 +1,77 @@
+{
+  "metadata": {
+    "name": "sw",
+    "group": "default"
+  },
+  "tags": [
+    {
+      "name": "trace_id",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "state",
+      "type": "TAG_TYPE_INT"
+    },
+    {
+      "name": "service_id",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "service_instance_id",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "endpoint_id",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "duration",
+      "type": "TAG_TYPE_INT"
+    },
+    {
+      "name": "start_time",
+      "type": "TAG_TYPE_INT"
+    },
+    {
+      "name": "http.method",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "status_code",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "db.type",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "db.instance",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "mq.queue",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "mq.topic",
+      "type": "TAG_TYPE_STRING"
+    },
+    {
+      "name": "mq.broker",
+      "type": "TAG_TYPE_STRING"
+    }
+  ],
+  "entity": {
+    "tag_names": [
+      "service_id",
+      "service_instance_id",
+      "state"
+    ]
+  },
+  "shard_num": 2,
+  "duration": {
+    "val": 7,
+    "unit": "DURATION_UNIT_DAY"
+  },
+  "updated_at": "2021-04-15T01:30:15.01Z"
+}
\ No newline at end of file
diff --git a/banyand/metadata/schema/schema.go 
b/banyand/metadata/schema/schema.go
new file mode 100644
index 0000000..8f4cd55
--- /dev/null
+++ b/banyand/metadata/schema/schema.go
@@ -0,0 +1,44 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package schema
+
+import (
+       "context"
+
+       commonv2 
"github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v2"
+       databasev2 
"github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
+)
+
+type ListOpt struct {
+       Group string
+}
+
+type Stream interface {
+       Get(ctx context.Context, metadata *commonv2.Metadata) 
(*databasev2.Stream, error)
+       List(ctx context.Context, opt ListOpt) ([]*databasev2.Stream, error)
+}
+
+type IndexRule interface {
+       Get(ctx context.Context, metadata *commonv2.Metadata) 
(*databasev2.IndexRule, error)
+       List(ctx context.Context, opt ListOpt) ([]*databasev2.IndexRule, error)
+}
+
+type IndexRuleBinding interface {
+       Get(ctx context.Context, metadata *commonv2.Metadata) 
(*databasev2.IndexRuleBinding, error)
+       List(ctx context.Context, opt ListOpt) ([]*databasev2.IndexRuleBinding, 
error)
+}
diff --git a/banyand/metadata/schema/sw.go b/banyand/metadata/schema/sw.go
new file mode 100644
index 0000000..c3e4387
--- /dev/null
+++ b/banyand/metadata/schema/sw.go
@@ -0,0 +1,124 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you under
+// the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package schema
+
+import (
+       "bytes"
+       "context"
+       "embed"
+
+       "github.com/golang/protobuf/jsonpb"
+
+       commonv2 
"github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v2"
+       databasev2 
"github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
+)
+
+var (
+       _ Stream    = (*streamRepo)(nil)
+       _ IndexRule = (*indexRuleRepo)(nil)
+
+       //go:embed data/index_rules/*.json
+       indexRuleStore embed.FS
+       //go:embed data/index_rule_binding.json
+       indexRuleBindingJSON string
+       //go:embed data/stream.json
+       streamJSON string
+)
+
+type streamRepo struct {
+       data *databasev2.Stream
+}
+
+func NewStream() (Stream, error) {
+       stream := &databasev2.Stream{}
+       if err := jsonpb.UnmarshalString(streamJSON, stream); err != nil {
+               return nil, err
+       }
+       return &streamRepo{
+               data: stream,
+       }, nil
+}
+
+func (l *streamRepo) Get(_ context.Context, _ *commonv2.Metadata) 
(*databasev2.Stream, error) {
+       return l.data, nil
+}
+
+func (l *streamRepo) List(ctx context.Context, _ ListOpt) 
([]*databasev2.Stream, error) {
+       s, err := l.Get(ctx, nil)
+       if err != nil {
+               return nil, err
+       }
+       return []*databasev2.Stream{s}, nil
+}
+
+type indexRuleRepo struct {
+       store embed.FS
+}
+
+func NewIndexRule() (IndexRule, error) {
+       return &indexRuleRepo{
+               store: indexRuleStore,
+       }, nil
+}
+
+func (i *indexRuleRepo) Get(_ context.Context, metadata *commonv2.Metadata) 
(*databasev2.IndexRule, error) {
+       bb, err := i.store.ReadFile("data/index_rules/" + metadata.Name + 
".json")
+       if err != nil {
+               return nil, err
+       }
+       indexRule := &databasev2.IndexRule{}
+       err = jsonpb.Unmarshal(bytes.NewReader(bb), indexRule)
+       if err != nil {
+               return nil, err
+       }
+       return indexRule, nil
+}
+
+func (i *indexRuleRepo) List(ctx context.Context, _ ListOpt) 
([]*databasev2.IndexRule, error) {
+       t, err := i.Get(ctx, nil)
+       if err != nil {
+               return nil, err
+       }
+       return []*databasev2.IndexRule{t}, nil
+}
+
+type indexRuleBindingRepo struct {
+       data *databasev2.IndexRuleBinding
+}
+
+func NewIndexRuleBinding() (IndexRuleBinding, error) {
+       indexRuleBinding := &databasev2.IndexRuleBinding{}
+       if err := jsonpb.UnmarshalString(indexRuleBindingJSON, 
indexRuleBinding); err != nil {
+               return nil, err
+       }
+       return &indexRuleBindingRepo{
+               data: indexRuleBinding,
+       }, nil
+}
+
+func (i *indexRuleBindingRepo) Get(_ context.Context, _ *commonv2.Metadata) 
(*databasev2.IndexRuleBinding, error) {
+       return i.data, nil
+}
+
+func (i *indexRuleBindingRepo) List(ctx context.Context, _ ListOpt) 
([]*databasev2.IndexRuleBinding, error) {
+       t, err := i.Get(ctx, nil)
+       if err != nil {
+               return nil, err
+       }
+       return []*databasev2.IndexRuleBinding{t}, nil
+}

Reply via email to