You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ha...@apache.org on 2021/08/24 14:49:16 UTC

[skywalking-banyandb] branch time-series updated: Add metadata module

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 <ha...@gmail.com>
AuthorDate: Tue Aug 24 22:43:26 2021 +0800

    Add metadata module
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
---
 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
+}