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/09/06 07:00:54 UTC
[skywalking-banyandb] branch time-series updated: Finish stream
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 31fb8cf Finish stream module
31fb8cf is described below
commit 31fb8cf1721b92801f356cd83f68b27a39f7b744
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Mon Sep 6 15:00:01 2021 +0800
Finish stream module
Signed-off-by: Gao Hongtao <ha...@gmail.com>
---
api/common/id.go | 7 +
api/proto/banyandb/model/v2/common.pb.go | 239 ++++++++--
api/proto/banyandb/model/v2/common.proto | 13 +
api/proto/banyandb/model/v2/query.pb.go | 498 ++++++++-------------
api/proto/banyandb/model/v2/query.proto | 28 +-
api/proto/banyandb/model/v2/write.pb.go | 298 ------------
api/proto/banyandb/stream/v2/query.pb.go | 224 +++++----
api/proto/banyandb/stream/v2/query.proto | 12 +-
api/proto/banyandb/stream/v2/write.pb.go | 78 ++--
api/proto/banyandb/stream/v2/write.proto | 6 +-
banyand/index/tsdb/field_map.go | 2 +-
banyand/kv/badger.go | 142 +++++-
banyand/kv/kv.go | 32 +-
banyand/storage/database_test.go | 4 +-
banyand/stream/index.go | 28 +-
banyand/stream/service.go | 16 +-
banyand/stream/stream.go | 24 +-
banyand/stream/stream_query.go | 117 +++++
banyand/stream/stream_write.go | 66 +--
banyand/stream/stream_write_test.go | 23 +-
banyand/tsdb/block.go | 89 +++-
banyand/tsdb/indexdb.go | 44 +-
banyand/tsdb/series.go | 225 ++--------
banyand/tsdb/series_seek.go | 128 ++++++
banyand/tsdb/series_seek_filter.go | 104 +++++
banyand/tsdb/series_seek_sort.go | 200 +++++++++
banyand/tsdb/series_write.go | 177 ++++++++
banyand/tsdb/seriesdb.go | 2 +-
banyand/tsdb/tsdb.go | 18 +-
pkg/index/index.go | 63 +++
.../index/tsdb => pkg/index/inverted}/field_map.go | 9 +-
.../write.proto => pkg/index/inverted/inverted.go | 45 +-
pkg/index/inverted/mem.go | 155 +++++++
pkg/index/inverted/mem_test.go | 308 +++++++++++++
pkg/index/inverted/term_map.go | 161 +++++++
.../field_map.go => pkg/index/posting/posting.go | 73 +--
pkg/index/posting/roaring/roaring.go | 214 +++++++++
pkg/index/search.go | 335 ++++++++++++++
38 files changed, 3098 insertions(+), 1109 deletions(-)
diff --git a/api/common/id.go b/api/common/id.go
index 6eafb8a..5442bcc 100644
--- a/api/common/id.go
+++ b/api/common/id.go
@@ -17,6 +17,13 @@
package common
+import "github.com/apache/skywalking-banyandb/pkg/convert"
+
type ChunkID uint64
type SeriesID uint64
type ShardID uint32
+type ItemID uint64
+
+func (s SeriesID) Marshal() []byte {
+ return convert.Uint64ToBytes(uint64(s))
+}
diff --git a/api/proto/banyandb/model/v2/common.pb.go b/api/proto/banyandb/model/v2/common.pb.go
index b6a1499..f848ce7 100644
--- a/api/proto/banyandb/model/v2/common.pb.go
+++ b/api/proto/banyandb/model/v2/common.pb.go
@@ -29,6 +29,7 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ structpb "google.golang.org/protobuf/types/known/structpb"
)
const (
@@ -226,28 +227,185 @@ func (x *IntArray) GetValue() []int64 {
return nil
}
+type TagValue struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Types that are assignable to Value:
+ // *TagValue_Null
+ // *TagValue_Str
+ // *TagValue_StrArray
+ // *TagValue_Int
+ // *TagValue_IntArray
+ // *TagValue_BinaryData
+ Value isTagValue_Value `protobuf_oneof:"value"`
+}
+
+func (x *TagValue) Reset() {
+ *x = TagValue{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_banyandb_model_v2_common_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *TagValue) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TagValue) ProtoMessage() {}
+
+func (x *TagValue) ProtoReflect() protoreflect.Message {
+ mi := &file_banyandb_model_v2_common_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TagValue.ProtoReflect.Descriptor instead.
+func (*TagValue) Descriptor() ([]byte, []int) {
+ return file_banyandb_model_v2_common_proto_rawDescGZIP(), []int{4}
+}
+
+func (m *TagValue) GetValue() isTagValue_Value {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (x *TagValue) GetNull() structpb.NullValue {
+ if x, ok := x.GetValue().(*TagValue_Null); ok {
+ return x.Null
+ }
+ return structpb.NullValue(0)
+}
+
+func (x *TagValue) GetStr() *Str {
+ if x, ok := x.GetValue().(*TagValue_Str); ok {
+ return x.Str
+ }
+ return nil
+}
+
+func (x *TagValue) GetStrArray() *StrArray {
+ if x, ok := x.GetValue().(*TagValue_StrArray); ok {
+ return x.StrArray
+ }
+ return nil
+}
+
+func (x *TagValue) GetInt() *Int {
+ if x, ok := x.GetValue().(*TagValue_Int); ok {
+ return x.Int
+ }
+ return nil
+}
+
+func (x *TagValue) GetIntArray() *IntArray {
+ if x, ok := x.GetValue().(*TagValue_IntArray); ok {
+ return x.IntArray
+ }
+ return nil
+}
+
+func (x *TagValue) GetBinaryData() []byte {
+ if x, ok := x.GetValue().(*TagValue_BinaryData); ok {
+ return x.BinaryData
+ }
+ return nil
+}
+
+type isTagValue_Value interface {
+ isTagValue_Value()
+}
+
+type TagValue_Null struct {
+ Null structpb.NullValue `protobuf:"varint,1,opt,name=null,proto3,enum=google.protobuf.NullValue,oneof"`
+}
+
+type TagValue_Str struct {
+ Str *Str `protobuf:"bytes,2,opt,name=str,proto3,oneof"`
+}
+
+type TagValue_StrArray struct {
+ StrArray *StrArray `protobuf:"bytes,3,opt,name=str_array,json=strArray,proto3,oneof"`
+}
+
+type TagValue_Int struct {
+ Int *Int `protobuf:"bytes,4,opt,name=int,proto3,oneof"`
+}
+
+type TagValue_IntArray struct {
+ IntArray *IntArray `protobuf:"bytes,5,opt,name=int_array,json=intArray,proto3,oneof"`
+}
+
+type TagValue_BinaryData struct {
+ BinaryData []byte `protobuf:"bytes,6,opt,name=binary_data,json=binaryData,proto3,oneof"`
+}
+
+func (*TagValue_Null) isTagValue_Value() {}
+
+func (*TagValue_Str) isTagValue_Value() {}
+
+func (*TagValue_StrArray) isTagValue_Value() {}
+
+func (*TagValue_Int) isTagValue_Value() {}
+
+func (*TagValue_IntArray) isTagValue_Value() {}
+
+func (*TagValue_BinaryData) isTagValue_Value() {}
+
var File_banyandb_model_v2_common_proto protoreflect.FileDescriptor
var file_banyandb_model_v2_common_proto_rawDesc = []byte{
0x0a, 0x1e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x11, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
- 0x2e, 0x76, 0x32, 0x22, 0x1b, 0x0a, 0x03, 0x53, 0x74, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x22, 0x1b, 0x0a, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x20, 0x0a,
- 0x08, 0x53, 0x74, 0x72, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
- 0x20, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x42, 0x6c, 0x0a, 0x27, 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, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x5a, 0x41, 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, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x62,
- 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x2e, 0x76, 0x32, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x22, 0x1b, 0x0a, 0x03, 0x53, 0x74, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x1b,
+ 0x0a, 0x03, 0x49, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x20, 0x0a, 0x08, 0x53,
+ 0x74, 0x72, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x20, 0x0a,
+ 0x08, 0x49, 0x6e, 0x74, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
+ 0xb8, 0x02, 0x0a, 0x08, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x30, 0x0a, 0x04,
+ 0x6e, 0x75, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4e, 0x75, 0x6c,
+ 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x75, 0x6c, 0x6c, 0x12, 0x2a,
+ 0x0a, 0x03, 0x73, 0x74, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61,
+ 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e,
+ 0x53, 0x74, 0x72, 0x48, 0x00, 0x52, 0x03, 0x73, 0x74, 0x72, 0x12, 0x3a, 0x0a, 0x09, 0x73, 0x74,
+ 0x72, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e,
+ 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76,
+ 0x32, 0x2e, 0x53, 0x74, 0x72, 0x41, 0x72, 0x72, 0x61, 0x79, 0x48, 0x00, 0x52, 0x08, 0x73, 0x74,
+ 0x72, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x03, 0x69, 0x6e, 0x74, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d,
+ 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x03, 0x69,
+ 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62,
+ 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6e, 0x74, 0x41, 0x72, 0x72,
+ 0x61, 0x79, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x21,
+ 0x0a, 0x0b, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0a, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74,
+ 0x61, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x6c, 0x0a, 0x27, 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, 0x6d, 0x6f, 0x64,
+ 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x5a, 0x41, 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,
+ 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -262,19 +420,26 @@ func file_banyandb_model_v2_common_proto_rawDescGZIP() []byte {
return file_banyandb_model_v2_common_proto_rawDescData
}
-var file_banyandb_model_v2_common_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_banyandb_model_v2_common_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_banyandb_model_v2_common_proto_goTypes = []interface{}{
- (*Str)(nil), // 0: banyandb.model.v2.Str
- (*Int)(nil), // 1: banyandb.model.v2.Int
- (*StrArray)(nil), // 2: banyandb.model.v2.StrArray
- (*IntArray)(nil), // 3: banyandb.model.v2.IntArray
+ (*Str)(nil), // 0: banyandb.model.v2.Str
+ (*Int)(nil), // 1: banyandb.model.v2.Int
+ (*StrArray)(nil), // 2: banyandb.model.v2.StrArray
+ (*IntArray)(nil), // 3: banyandb.model.v2.IntArray
+ (*TagValue)(nil), // 4: banyandb.model.v2.TagValue
+ (structpb.NullValue)(0), // 5: google.protobuf.NullValue
}
var file_banyandb_model_v2_common_proto_depIdxs = []int32{
- 0, // [0:0] is the sub-list for method output_type
- 0, // [0:0] is the sub-list for method input_type
- 0, // [0:0] is the sub-list for extension type_name
- 0, // [0:0] is the sub-list for extension extendee
- 0, // [0:0] is the sub-list for field type_name
+ 5, // 0: banyandb.model.v2.TagValue.null:type_name -> google.protobuf.NullValue
+ 0, // 1: banyandb.model.v2.TagValue.str:type_name -> banyandb.model.v2.Str
+ 2, // 2: banyandb.model.v2.TagValue.str_array:type_name -> banyandb.model.v2.StrArray
+ 1, // 3: banyandb.model.v2.TagValue.int:type_name -> banyandb.model.v2.Int
+ 3, // 4: banyandb.model.v2.TagValue.int_array:type_name -> banyandb.model.v2.IntArray
+ 5, // [5:5] is the sub-list for method output_type
+ 5, // [5:5] is the sub-list for method input_type
+ 5, // [5:5] is the sub-list for extension type_name
+ 5, // [5:5] is the sub-list for extension extendee
+ 0, // [0:5] is the sub-list for field type_name
}
func init() { file_banyandb_model_v2_common_proto_init() }
@@ -331,6 +496,26 @@ func file_banyandb_model_v2_common_proto_init() {
return nil
}
}
+ file_banyandb_model_v2_common_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*TagValue); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ file_banyandb_model_v2_common_proto_msgTypes[4].OneofWrappers = []interface{}{
+ (*TagValue_Null)(nil),
+ (*TagValue_Str)(nil),
+ (*TagValue_StrArray)(nil),
+ (*TagValue_Int)(nil),
+ (*TagValue_IntArray)(nil),
+ (*TagValue_BinaryData)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -338,7 +523,7 @@ func file_banyandb_model_v2_common_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_banyandb_model_v2_common_proto_rawDesc,
NumEnums: 0,
- NumMessages: 4,
+ NumMessages: 5,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/api/proto/banyandb/model/v2/common.proto b/api/proto/banyandb/model/v2/common.proto
index d48f28c..e9c51a5 100644
--- a/api/proto/banyandb/model/v2/common.proto
+++ b/api/proto/banyandb/model/v2/common.proto
@@ -22,6 +22,8 @@ package banyandb.model.v2;
option java_package = "org.apache.skywalking.banyandb.model.v2";
option go_package = "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2";
+import "google/protobuf/struct.proto";
+
message Str {
string value = 1;
}
@@ -37,3 +39,14 @@ message StrArray {
message IntArray {
repeated int64 value = 1;
}
+
+message TagValue {
+ oneof value {
+ google.protobuf.NullValue null = 1;
+ Str str = 2;
+ StrArray str_array = 3;
+ Int int = 4;
+ IntArray int_array = 5;
+ bytes binary_data = 6;
+ }
+}
diff --git a/api/proto/banyandb/model/v2/query.pb.go b/api/proto/banyandb/model/v2/query.pb.go
index b6cda1c..330251a 100644
--- a/api/proto/banyandb/model/v2/query.pb.go
+++ b/api/proto/banyandb/model/v2/query.pb.go
@@ -30,8 +30,6 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
-
- v2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
)
const (
@@ -45,23 +43,23 @@ const (
// For EQ, NE, LT, GT, LE and GE, only one operand should be given, i.e. one-to-one relationship.
// HAVING and NOT_HAVING allow multi-value to be the operand such as array/vector, i.e. one-to-many relationship.
// For example, "keyA" contains "valueA" **and** "valueB"
-type PairQuery_BinaryOp int32
+type Condition_BinaryOp int32
const (
- PairQuery_BINARY_OP_UNSPECIFIED PairQuery_BinaryOp = 0
- PairQuery_BINARY_OP_EQ PairQuery_BinaryOp = 1
- PairQuery_BINARY_OP_NE PairQuery_BinaryOp = 2
- PairQuery_BINARY_OP_LT PairQuery_BinaryOp = 3
- PairQuery_BINARY_OP_GT PairQuery_BinaryOp = 4
- PairQuery_BINARY_OP_LE PairQuery_BinaryOp = 5
- PairQuery_BINARY_OP_GE PairQuery_BinaryOp = 6
- PairQuery_BINARY_OP_HAVING PairQuery_BinaryOp = 7
- PairQuery_BINARY_OP_NOT_HAVING PairQuery_BinaryOp = 8
+ Condition_BINARY_OP_UNSPECIFIED Condition_BinaryOp = 0
+ Condition_BINARY_OP_EQ Condition_BinaryOp = 1
+ Condition_BINARY_OP_NE Condition_BinaryOp = 2
+ Condition_BINARY_OP_LT Condition_BinaryOp = 3
+ Condition_BINARY_OP_GT Condition_BinaryOp = 4
+ Condition_BINARY_OP_LE Condition_BinaryOp = 5
+ Condition_BINARY_OP_GE Condition_BinaryOp = 6
+ Condition_BINARY_OP_HAVING Condition_BinaryOp = 7
+ Condition_BINARY_OP_NOT_HAVING Condition_BinaryOp = 8
)
-// Enum value maps for PairQuery_BinaryOp.
+// Enum value maps for Condition_BinaryOp.
var (
- PairQuery_BinaryOp_name = map[int32]string{
+ Condition_BinaryOp_name = map[int32]string{
0: "BINARY_OP_UNSPECIFIED",
1: "BINARY_OP_EQ",
2: "BINARY_OP_NE",
@@ -72,7 +70,7 @@ var (
7: "BINARY_OP_HAVING",
8: "BINARY_OP_NOT_HAVING",
}
- PairQuery_BinaryOp_value = map[string]int32{
+ Condition_BinaryOp_value = map[string]int32{
"BINARY_OP_UNSPECIFIED": 0,
"BINARY_OP_EQ": 1,
"BINARY_OP_NE": 2,
@@ -85,31 +83,31 @@ var (
}
)
-func (x PairQuery_BinaryOp) Enum() *PairQuery_BinaryOp {
- p := new(PairQuery_BinaryOp)
+func (x Condition_BinaryOp) Enum() *Condition_BinaryOp {
+ p := new(Condition_BinaryOp)
*p = x
return p
}
-func (x PairQuery_BinaryOp) String() string {
+func (x Condition_BinaryOp) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
-func (PairQuery_BinaryOp) Descriptor() protoreflect.EnumDescriptor {
+func (Condition_BinaryOp) Descriptor() protoreflect.EnumDescriptor {
return file_banyandb_model_v2_query_proto_enumTypes[0].Descriptor()
}
-func (PairQuery_BinaryOp) Type() protoreflect.EnumType {
+func (Condition_BinaryOp) Type() protoreflect.EnumType {
return &file_banyandb_model_v2_query_proto_enumTypes[0]
}
-func (x PairQuery_BinaryOp) Number() protoreflect.EnumNumber {
+func (x Condition_BinaryOp) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
-// Deprecated: Use PairQuery_BinaryOp.Descriptor instead.
-func (PairQuery_BinaryOp) EnumDescriptor() ([]byte, []int) {
- return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{1, 0}
+// Deprecated: Use Condition_BinaryOp.Descriptor instead.
+func (Condition_BinaryOp) EnumDescriptor() ([]byte, []int) {
+ return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{2, 0}
}
type QueryOrder_Sort int32
@@ -158,30 +156,24 @@ func (x QueryOrder_Sort) Number() protoreflect.EnumNumber {
// Deprecated: Use QueryOrder_Sort.Descriptor instead.
func (QueryOrder_Sort) EnumDescriptor() ([]byte, []int) {
- return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{2, 0}
+ return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{3, 0}
}
// Pair is the building block of a record which is equivalent to a key-value pair.
// In the context of Trace, it could be metadata of a trace such as service_name, service_instance, etc.
// Besides, other tags are organized in key-value pair in the underlying storage layer.
// One should notice that the values can be a multi-value.
-type TypedPair struct {
+type Tag struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
- // Types that are assignable to Typed:
- // *TypedPair_NullPair
- // *TypedPair_IntPair
- // *TypedPair_StrPair
- // *TypedPair_IntArrayPair
- // *TypedPair_StrArrayPair
- Typed isTypedPair_Typed `protobuf_oneof:"typed"`
+ Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ Value *TagValue `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
-func (x *TypedPair) Reset() {
- *x = TypedPair{}
+func (x *Tag) Reset() {
+ *x = Tag{}
if protoimpl.UnsafeEnabled {
mi := &file_banyandb_model_v2_query_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -189,13 +181,13 @@ func (x *TypedPair) Reset() {
}
}
-func (x *TypedPair) String() string {
+func (x *Tag) String() string {
return protoimpl.X.MessageStringOf(x)
}
-func (*TypedPair) ProtoMessage() {}
+func (*Tag) ProtoMessage() {}
-func (x *TypedPair) ProtoReflect() protoreflect.Message {
+func (x *Tag) ProtoReflect() protoreflect.Message {
mi := &file_banyandb_model_v2_query_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -207,123 +199,109 @@ func (x *TypedPair) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
-// Deprecated: Use TypedPair.ProtoReflect.Descriptor instead.
-func (*TypedPair) Descriptor() ([]byte, []int) {
+// Deprecated: Use Tag.ProtoReflect.Descriptor instead.
+func (*Tag) Descriptor() ([]byte, []int) {
return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{0}
}
-func (x *TypedPair) GetKey() string {
+func (x *Tag) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
-func (m *TypedPair) GetTyped() isTypedPair_Typed {
- if m != nil {
- return m.Typed
- }
- return nil
-}
-
-func (x *TypedPair) GetNullPair() *TypedPair_NullWithType {
- if x, ok := x.GetTyped().(*TypedPair_NullPair); ok {
- return x.NullPair
- }
- return nil
-}
-
-func (x *TypedPair) GetIntPair() *Int {
- if x, ok := x.GetTyped().(*TypedPair_IntPair); ok {
- return x.IntPair
+func (x *Tag) GetValue() *TagValue {
+ if x != nil {
+ return x.Value
}
return nil
}
-func (x *TypedPair) GetStrPair() *Str {
- if x, ok := x.GetTyped().(*TypedPair_StrPair); ok {
- return x.StrPair
- }
- return nil
-}
+type TagFamily struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
-func (x *TypedPair) GetIntArrayPair() *IntArray {
- if x, ok := x.GetTyped().(*TypedPair_IntArrayPair); ok {
- return x.IntArrayPair
- }
- return nil
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Tags []*Tag `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty"`
}
-func (x *TypedPair) GetStrArrayPair() *StrArray {
- if x, ok := x.GetTyped().(*TypedPair_StrArrayPair); ok {
- return x.StrArrayPair
+func (x *TagFamily) Reset() {
+ *x = TagFamily{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
}
- return nil
}
-type isTypedPair_Typed interface {
- isTypedPair_Typed()
+func (x *TagFamily) String() string {
+ return protoimpl.X.MessageStringOf(x)
}
-type TypedPair_NullPair struct {
- NullPair *TypedPair_NullWithType `protobuf:"bytes,2,opt,name=null_pair,json=nullPair,proto3,oneof"`
-}
+func (*TagFamily) ProtoMessage() {}
-type TypedPair_IntPair struct {
- IntPair *Int `protobuf:"bytes,3,opt,name=int_pair,json=intPair,proto3,oneof"`
+func (x *TagFamily) ProtoReflect() protoreflect.Message {
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
}
-type TypedPair_StrPair struct {
- StrPair *Str `protobuf:"bytes,4,opt,name=str_pair,json=strPair,proto3,oneof"`
+// Deprecated: Use TagFamily.ProtoReflect.Descriptor instead.
+func (*TagFamily) Descriptor() ([]byte, []int) {
+ return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{1}
}
-type TypedPair_IntArrayPair struct {
- IntArrayPair *IntArray `protobuf:"bytes,5,opt,name=int_array_pair,json=intArrayPair,proto3,oneof"`
+func (x *TagFamily) GetName() string {
+ if x != nil {
+ return x.Name
+ }
+ return ""
}
-type TypedPair_StrArrayPair struct {
- StrArrayPair *StrArray `protobuf:"bytes,6,opt,name=str_array_pair,json=strArrayPair,proto3,oneof"`
+func (x *TagFamily) GetTags() []*Tag {
+ if x != nil {
+ return x.Tags
+ }
+ return nil
}
-func (*TypedPair_NullPair) isTypedPair_Typed() {}
-
-func (*TypedPair_IntPair) isTypedPair_Typed() {}
-
-func (*TypedPair_StrPair) isTypedPair_Typed() {}
-
-func (*TypedPair_IntArrayPair) isTypedPair_Typed() {}
-
-func (*TypedPair_StrArrayPair) isTypedPair_Typed() {}
-
-// PairQuery consists of the query condition with a single binary operator to be imposed
+// Condition consists of the query condition with a single binary operator to be imposed
// For 1:1 BinaryOp, values in condition must be an array with length = 1,
// while for 1:N BinaryOp, values can be an array with length >= 1.
-type PairQuery struct {
+type Condition struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- Op PairQuery_BinaryOp `protobuf:"varint,1,opt,name=op,proto3,enum=banyandb.model.v2.PairQuery_BinaryOp" json:"op,omitempty"`
- Condition *TypedPair `protobuf:"bytes,2,opt,name=condition,proto3" json:"condition,omitempty"`
+ Op Condition_BinaryOp `protobuf:"varint,1,opt,name=op,proto3,enum=banyandb.model.v2.Condition_BinaryOp" json:"op,omitempty"`
+ Value *TagValue `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
-func (x *PairQuery) Reset() {
- *x = PairQuery{}
+func (x *Condition) Reset() {
+ *x = Condition{}
if protoimpl.UnsafeEnabled {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[1]
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
-func (x *PairQuery) String() string {
+func (x *Condition) String() string {
return protoimpl.X.MessageStringOf(x)
}
-func (*PairQuery) ProtoMessage() {}
+func (*Condition) ProtoMessage() {}
-func (x *PairQuery) ProtoReflect() protoreflect.Message {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[1]
+func (x *Condition) ProtoReflect() protoreflect.Message {
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -334,21 +312,21 @@ func (x *PairQuery) ProtoReflect() protoreflect.Message {
return mi.MessageOf(x)
}
-// Deprecated: Use PairQuery.ProtoReflect.Descriptor instead.
-func (*PairQuery) Descriptor() ([]byte, []int) {
- return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{1}
+// Deprecated: Use Condition.ProtoReflect.Descriptor instead.
+func (*Condition) Descriptor() ([]byte, []int) {
+ return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{2}
}
-func (x *PairQuery) GetOp() PairQuery_BinaryOp {
+func (x *Condition) GetOp() Condition_BinaryOp {
if x != nil {
return x.Op
}
- return PairQuery_BINARY_OP_UNSPECIFIED
+ return Condition_BINARY_OP_UNSPECIFIED
}
-func (x *PairQuery) GetCondition() *TypedPair {
+func (x *Condition) GetValue() *TagValue {
if x != nil {
- return x.Condition
+ return x.Value
}
return nil
}
@@ -367,7 +345,7 @@ type QueryOrder struct {
func (x *QueryOrder) Reset() {
*x = QueryOrder{}
if protoimpl.UnsafeEnabled {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[2]
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -380,7 +358,7 @@ func (x *QueryOrder) String() string {
func (*QueryOrder) ProtoMessage() {}
func (x *QueryOrder) ProtoReflect() protoreflect.Message {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[2]
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -393,7 +371,7 @@ func (x *QueryOrder) ProtoReflect() protoreflect.Message {
// Deprecated: Use QueryOrder.ProtoReflect.Descriptor instead.
func (*QueryOrder) Descriptor() ([]byte, []int) {
- return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{2}
+ return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{3}
}
func (x *QueryOrder) GetKeyName() string {
@@ -416,16 +394,14 @@ type Projection struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- // whether binary part is needed
- DataBinary bool `protobuf:"varint,1,opt,name=data_binary,json=dataBinary,proto3" json:"data_binary,omitempty"`
// The key_name refers to the key(s) of Pair(s).
- KeyNames []string `protobuf:"bytes,2,rep,name=key_names,json=keyNames,proto3" json:"key_names,omitempty"`
+ FagFamilies []*TagFamily `protobuf:"bytes,1,rep,name=fag_families,json=fagFamilies,proto3" json:"fag_families,omitempty"`
}
func (x *Projection) Reset() {
*x = Projection{}
if protoimpl.UnsafeEnabled {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[3]
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -438,7 +414,7 @@ func (x *Projection) String() string {
func (*Projection) ProtoMessage() {}
func (x *Projection) ProtoReflect() protoreflect.Message {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[3]
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -451,19 +427,12 @@ func (x *Projection) ProtoReflect() protoreflect.Message {
// Deprecated: Use Projection.ProtoReflect.Descriptor instead.
func (*Projection) Descriptor() ([]byte, []int) {
- return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{3}
-}
-
-func (x *Projection) GetDataBinary() bool {
- if x != nil {
- return x.DataBinary
- }
- return false
+ return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{4}
}
-func (x *Projection) GetKeyNames() []string {
+func (x *Projection) GetFagFamilies() []*TagFamily {
if x != nil {
- return x.KeyNames
+ return x.FagFamilies
}
return nil
}
@@ -482,7 +451,7 @@ type TimeRange struct {
func (x *TimeRange) Reset() {
*x = TimeRange{}
if protoimpl.UnsafeEnabled {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[4]
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -495,7 +464,7 @@ func (x *TimeRange) String() string {
func (*TimeRange) ProtoMessage() {}
func (x *TimeRange) ProtoReflect() protoreflect.Message {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[4]
+ mi := &file_banyandb_model_v2_query_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -508,7 +477,7 @@ func (x *TimeRange) ProtoReflect() protoreflect.Message {
// Deprecated: Use TimeRange.ProtoReflect.Descriptor instead.
func (*TimeRange) Descriptor() ([]byte, []int) {
- return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{4}
+ return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{5}
}
func (x *TimeRange) GetBegin() *timestamppb.Timestamp {
@@ -525,53 +494,6 @@ func (x *TimeRange) GetEnd() *timestamppb.Timestamp {
return nil
}
-type TypedPair_NullWithType struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Type v2.TagType `protobuf:"varint,1,opt,name=type,proto3,enum=banyandb.database.v2.TagType" json:"type,omitempty"`
-}
-
-func (x *TypedPair_NullWithType) Reset() {
- *x = TypedPair_NullWithType{}
- if protoimpl.UnsafeEnabled {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[5]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *TypedPair_NullWithType) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*TypedPair_NullWithType) ProtoMessage() {}
-
-func (x *TypedPair_NullWithType) ProtoReflect() protoreflect.Message {
- mi := &file_banyandb_model_v2_query_proto_msgTypes[5]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use TypedPair_NullWithType.ProtoReflect.Descriptor instead.
-func (*TypedPair_NullWithType) Descriptor() ([]byte, []int) {
- return file_banyandb_model_v2_query_proto_rawDescGZIP(), []int{0, 0}
-}
-
-func (x *TypedPair_NullWithType) GetType() v2.TagType {
- if x != nil {
- return x.Type
- }
- return v2.TagType(0)
-}
-
var File_banyandb_model_v2_query_proto protoreflect.FileDescriptor
var file_banyandb_model_v2_query_proto_rawDesc = []byte{
@@ -582,85 +504,65 @@ var file_banyandb_model_v2_query_proto_rawDesc = []byte{
0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f, 0x6d, 0x6f,
0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f, 0x64, 0x61,
- 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x03, 0x0a, 0x09, 0x54, 0x79, 0x70, 0x65, 0x64,
- 0x50, 0x61, 0x69, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x48, 0x0a, 0x09, 0x6e, 0x75, 0x6c, 0x6c, 0x5f, 0x70,
- 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x62, 0x61, 0x6e, 0x79,
- 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x79,
- 0x70, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x57, 0x69, 0x74, 0x68,
- 0x54, 0x79, 0x70, 0x65, 0x48, 0x00, 0x52, 0x08, 0x6e, 0x75, 0x6c, 0x6c, 0x50, 0x61, 0x69, 0x72,
- 0x12, 0x33, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f,
- 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x07, 0x69, 0x6e,
- 0x74, 0x50, 0x61, 0x69, 0x72, 0x12, 0x33, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x5f, 0x70, 0x61, 0x69,
- 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e,
- 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x72, 0x48,
- 0x00, 0x52, 0x07, 0x73, 0x74, 0x72, 0x50, 0x61, 0x69, 0x72, 0x12, 0x43, 0x0a, 0x0e, 0x69, 0x6e,
- 0x74, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f,
- 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6e, 0x74, 0x41, 0x72, 0x72, 0x61, 0x79, 0x48,
- 0x00, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x41, 0x72, 0x72, 0x61, 0x79, 0x50, 0x61, 0x69, 0x72, 0x12,
- 0x43, 0x0a, 0x0e, 0x73, 0x74, 0x72, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x5f, 0x70, 0x61, 0x69,
- 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e,
- 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x72, 0x41,
- 0x72, 0x72, 0x61, 0x79, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x74, 0x72, 0x41, 0x72, 0x72, 0x61, 0x79,
- 0x50, 0x61, 0x69, 0x72, 0x1a, 0x41, 0x0a, 0x0c, 0x4e, 0x75, 0x6c, 0x6c, 0x57, 0x69, 0x74, 0x68,
- 0x54, 0x79, 0x70, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x64, 0x61,
- 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x61, 0x67, 0x54, 0x79, 0x70,
- 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x64,
- 0x22, 0xc2, 0x02, 0x0a, 0x09, 0x50, 0x61, 0x69, 0x72, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x35,
- 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x61, 0x6e,
- 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x50,
- 0x61, 0x69, 0x72, 0x51, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x4f,
- 0x70, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x3a, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69,
- 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61,
- 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x79, 0x70,
- 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
- 0x6e, 0x22, 0xc1, 0x01, 0x0a, 0x08, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x4f, 0x70, 0x12, 0x19,
- 0x0a, 0x15, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x55, 0x4e, 0x53, 0x50,
- 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e,
- 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x45, 0x51, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42,
- 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a,
- 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x4c, 0x54, 0x10, 0x03, 0x12,
- 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x47, 0x54, 0x10,
- 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x4c,
- 0x45, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50,
- 0x5f, 0x47, 0x45, 0x10, 0x06, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f,
- 0x4f, 0x50, 0x5f, 0x48, 0x41, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x12, 0x18, 0x0a, 0x14, 0x42,
- 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x48, 0x41, 0x56,
- 0x49, 0x4e, 0x47, 0x10, 0x08, 0x22, 0x9a, 0x01, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f,
- 0x72, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12,
- 0x36, 0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e,
- 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76,
- 0x32, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x53, 0x6f, 0x72,
- 0x74, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x22, 0x39, 0x0a, 0x04, 0x53, 0x6f, 0x72, 0x74, 0x12,
- 0x14, 0x0a, 0x10, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
- 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x44, 0x45,
- 0x53, 0x43, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x41, 0x53, 0x43,
- 0x10, 0x02, 0x22, 0x4a, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
- 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x42, 0x69, 0x6e, 0x61, 0x72,
- 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02,
- 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x6b,
- 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x62,
- 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 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, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x2c, 0x0a,
- 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 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, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x6c, 0x0a, 0x27, 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, 0x6d, 0x6f,
- 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x5a, 0x41, 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, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x33,
+ 0x6f, 0x74, 0x6f, 0x22, 0x4a, 0x0a, 0x03, 0x54, 0x61, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61,
+ 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e,
+ 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
+ 0x4b, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+ 0x12, 0x2a, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
+ 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e,
+ 0x76, 0x32, 0x2e, 0x54, 0x61, 0x67, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0xb9, 0x02, 0x0a,
+ 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x02, 0x6f, 0x70,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64,
+ 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x4f, 0x70, 0x52, 0x02, 0x6f,
+ 0x70, 0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65,
+ 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x08, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x4f,
+ 0x70, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x55,
+ 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c,
+ 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x45, 0x51, 0x10, 0x01, 0x12, 0x10,
+ 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x4e, 0x45, 0x10, 0x02,
+ 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x4c, 0x54,
+ 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f,
+ 0x47, 0x54, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f,
+ 0x50, 0x5f, 0x4c, 0x45, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59,
+ 0x5f, 0x4f, 0x50, 0x5f, 0x47, 0x45, 0x10, 0x06, 0x12, 0x14, 0x0a, 0x10, 0x42, 0x49, 0x4e, 0x41,
+ 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x48, 0x41, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x12, 0x18,
+ 0x0a, 0x14, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x50, 0x5f, 0x4e, 0x4f, 0x54, 0x5f,
+ 0x48, 0x41, 0x56, 0x49, 0x4e, 0x47, 0x10, 0x08, 0x22, 0x9a, 0x01, 0x0a, 0x0a, 0x51, 0x75, 0x65,
+ 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61,
+ 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
+ 0x32, 0x22, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65,
+ 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x2e,
+ 0x53, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x22, 0x39, 0x0a, 0x04, 0x53, 0x6f,
+ 0x72, 0x74, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
+ 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x4f, 0x52, 0x54,
+ 0x5f, 0x44, 0x45, 0x53, 0x43, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x4f, 0x52, 0x54, 0x5f,
+ 0x41, 0x53, 0x43, 0x10, 0x02, 0x22, 0x4d, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x0c, 0x66, 0x61, 0x67, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c,
+ 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79,
+ 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x61,
+ 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x0b, 0x66, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69,
+ 0x6c, 0x69, 0x65, 0x73, 0x22, 0x6b, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67,
+ 0x65, 0x12, 0x30, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x01, 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, 0x05, 0x62, 0x65,
+ 0x67, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 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, 0x03, 0x65, 0x6e,
+ 0x64, 0x42, 0x6c, 0x0a, 0x27, 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, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x5a, 0x41, 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, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x62,
+ 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -678,38 +580,31 @@ func file_banyandb_model_v2_query_proto_rawDescGZIP() []byte {
var file_banyandb_model_v2_query_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_banyandb_model_v2_query_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_banyandb_model_v2_query_proto_goTypes = []interface{}{
- (PairQuery_BinaryOp)(0), // 0: banyandb.model.v2.PairQuery.BinaryOp
- (QueryOrder_Sort)(0), // 1: banyandb.model.v2.QueryOrder.Sort
- (*TypedPair)(nil), // 2: banyandb.model.v2.TypedPair
- (*PairQuery)(nil), // 3: banyandb.model.v2.PairQuery
- (*QueryOrder)(nil), // 4: banyandb.model.v2.QueryOrder
- (*Projection)(nil), // 5: banyandb.model.v2.Projection
- (*TimeRange)(nil), // 6: banyandb.model.v2.TimeRange
- (*TypedPair_NullWithType)(nil), // 7: banyandb.model.v2.TypedPair.NullWithType
- (*Int)(nil), // 8: banyandb.model.v2.Int
- (*Str)(nil), // 9: banyandb.model.v2.Str
- (*IntArray)(nil), // 10: banyandb.model.v2.IntArray
- (*StrArray)(nil), // 11: banyandb.model.v2.StrArray
- (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp
- (v2.TagType)(0), // 13: banyandb.database.v2.TagType
+ (Condition_BinaryOp)(0), // 0: banyandb.model.v2.Condition.BinaryOp
+ (QueryOrder_Sort)(0), // 1: banyandb.model.v2.QueryOrder.Sort
+ (*Tag)(nil), // 2: banyandb.model.v2.Tag
+ (*TagFamily)(nil), // 3: banyandb.model.v2.TagFamily
+ (*Condition)(nil), // 4: banyandb.model.v2.Condition
+ (*QueryOrder)(nil), // 5: banyandb.model.v2.QueryOrder
+ (*Projection)(nil), // 6: banyandb.model.v2.Projection
+ (*TimeRange)(nil), // 7: banyandb.model.v2.TimeRange
+ (*TagValue)(nil), // 8: banyandb.model.v2.TagValue
+ (*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp
}
var file_banyandb_model_v2_query_proto_depIdxs = []int32{
- 7, // 0: banyandb.model.v2.TypedPair.null_pair:type_name -> banyandb.model.v2.TypedPair.NullWithType
- 8, // 1: banyandb.model.v2.TypedPair.int_pair:type_name -> banyandb.model.v2.Int
- 9, // 2: banyandb.model.v2.TypedPair.str_pair:type_name -> banyandb.model.v2.Str
- 10, // 3: banyandb.model.v2.TypedPair.int_array_pair:type_name -> banyandb.model.v2.IntArray
- 11, // 4: banyandb.model.v2.TypedPair.str_array_pair:type_name -> banyandb.model.v2.StrArray
- 0, // 5: banyandb.model.v2.PairQuery.op:type_name -> banyandb.model.v2.PairQuery.BinaryOp
- 2, // 6: banyandb.model.v2.PairQuery.condition:type_name -> banyandb.model.v2.TypedPair
- 1, // 7: banyandb.model.v2.QueryOrder.sort:type_name -> banyandb.model.v2.QueryOrder.Sort
- 12, // 8: banyandb.model.v2.TimeRange.begin:type_name -> google.protobuf.Timestamp
- 12, // 9: banyandb.model.v2.TimeRange.end:type_name -> google.protobuf.Timestamp
- 13, // 10: banyandb.model.v2.TypedPair.NullWithType.type:type_name -> banyandb.database.v2.TagType
- 11, // [11:11] is the sub-list for method output_type
- 11, // [11:11] is the sub-list for method input_type
- 11, // [11:11] is the sub-list for extension type_name
- 11, // [11:11] is the sub-list for extension extendee
- 0, // [0:11] is the sub-list for field type_name
+ 8, // 0: banyandb.model.v2.Tag.value:type_name -> banyandb.model.v2.TagValue
+ 2, // 1: banyandb.model.v2.TagFamily.tags:type_name -> banyandb.model.v2.Tag
+ 0, // 2: banyandb.model.v2.Condition.op:type_name -> banyandb.model.v2.Condition.BinaryOp
+ 8, // 3: banyandb.model.v2.Condition.value:type_name -> banyandb.model.v2.TagValue
+ 1, // 4: banyandb.model.v2.QueryOrder.sort:type_name -> banyandb.model.v2.QueryOrder.Sort
+ 3, // 5: banyandb.model.v2.Projection.fag_families:type_name -> banyandb.model.v2.TagFamily
+ 9, // 6: banyandb.model.v2.TimeRange.begin:type_name -> google.protobuf.Timestamp
+ 9, // 7: banyandb.model.v2.TimeRange.end:type_name -> google.protobuf.Timestamp
+ 8, // [8:8] is the sub-list for method output_type
+ 8, // [8:8] is the sub-list for method input_type
+ 8, // [8:8] is the sub-list for extension type_name
+ 8, // [8:8] is the sub-list for extension extendee
+ 0, // [0:8] is the sub-list for field type_name
}
func init() { file_banyandb_model_v2_query_proto_init() }
@@ -720,7 +615,7 @@ func file_banyandb_model_v2_query_proto_init() {
file_banyandb_model_v2_common_proto_init()
if !protoimpl.UnsafeEnabled {
file_banyandb_model_v2_query_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*TypedPair); i {
+ switch v := v.(*Tag); i {
case 0:
return &v.state
case 1:
@@ -732,7 +627,7 @@ func file_banyandb_model_v2_query_proto_init() {
}
}
file_banyandb_model_v2_query_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PairQuery); i {
+ switch v := v.(*TagFamily); i {
case 0:
return &v.state
case 1:
@@ -744,7 +639,7 @@ func file_banyandb_model_v2_query_proto_init() {
}
}
file_banyandb_model_v2_query_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*QueryOrder); i {
+ switch v := v.(*Condition); i {
case 0:
return &v.state
case 1:
@@ -756,7 +651,7 @@ func file_banyandb_model_v2_query_proto_init() {
}
}
file_banyandb_model_v2_query_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Projection); i {
+ switch v := v.(*QueryOrder); i {
case 0:
return &v.state
case 1:
@@ -768,7 +663,7 @@ func file_banyandb_model_v2_query_proto_init() {
}
}
file_banyandb_model_v2_query_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*TimeRange); i {
+ switch v := v.(*Projection); i {
case 0:
return &v.state
case 1:
@@ -780,7 +675,7 @@ func file_banyandb_model_v2_query_proto_init() {
}
}
file_banyandb_model_v2_query_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*TypedPair_NullWithType); i {
+ switch v := v.(*TimeRange); i {
case 0:
return &v.state
case 1:
@@ -792,13 +687,6 @@ func file_banyandb_model_v2_query_proto_init() {
}
}
}
- file_banyandb_model_v2_query_proto_msgTypes[0].OneofWrappers = []interface{}{
- (*TypedPair_NullPair)(nil),
- (*TypedPair_IntPair)(nil),
- (*TypedPair_StrPair)(nil),
- (*TypedPair_IntArrayPair)(nil),
- (*TypedPair_StrArrayPair)(nil),
- }
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
diff --git a/api/proto/banyandb/model/v2/query.proto b/api/proto/banyandb/model/v2/query.proto
index 2d4b7d3..ed39c61 100644
--- a/api/proto/banyandb/model/v2/query.proto
+++ b/api/proto/banyandb/model/v2/query.proto
@@ -24,31 +24,25 @@ package banyandb.model.v2;
import "google/protobuf/timestamp.proto";
import "banyandb/model/v2/common.proto";
-import "banyandb/database/v2/schema.proto";
// Pair is the building block of a record which is equivalent to a key-value pair.
// In the context of Trace, it could be metadata of a trace such as service_name, service_instance, etc.
// Besides, other tags are organized in key-value pair in the underlying storage layer.
// One should notice that the values can be a multi-value.
-message TypedPair {
+message Tag {
string key = 1;
- oneof typed {
- NullWithType null_pair = 2;
- Int int_pair = 3;
- Str str_pair = 4;
- IntArray int_array_pair = 5;
- StrArray str_array_pair = 6;
- }
+ TagValue value = 2;
+}
- message NullWithType {
- database.v2.TagType type = 1;
- }
+message TagFamily {
+ string name = 1;
+ repeated Tag tags = 2;
}
-// PairQuery consists of the query condition with a single binary operator to be imposed
+// Condition consists of the query condition with a single binary operator to be imposed
// For 1:1 BinaryOp, values in condition must be an array with length = 1,
// while for 1:N BinaryOp, values can be an array with length >= 1.
-message PairQuery {
+message Condition {
// BinaryOp specifies the operation imposed to the given query condition
// For EQ, NE, LT, GT, LE and GE, only one operand should be given, i.e. one-to-one relationship.
// HAVING and NOT_HAVING allow multi-value to be the operand such as array/vector, i.e. one-to-many relationship.
@@ -65,7 +59,7 @@ message PairQuery {
BINARY_OP_NOT_HAVING = 8;
}
BinaryOp op = 1;
- TypedPair condition = 2;
+ TagValue value = 2;
}
// QueryOrder means a Sort operation to be done for a given tag.
@@ -82,10 +76,8 @@ message QueryOrder {
// Projection is used to select the names of keys to be returned.
message Projection {
- // whether binary part is needed
- bool data_binary = 1;
// The key_name refers to the key(s) of Pair(s).
- repeated string key_names = 2;
+ repeated TagFamily fag_families = 1;
}
// TimeRange is a range query for uint64,
diff --git a/api/proto/banyandb/model/v2/write.pb.go b/api/proto/banyandb/model/v2/write.pb.go
deleted file mode 100644
index 1640f11..0000000
--- a/api/proto/banyandb/model/v2/write.pb.go
+++ /dev/null
@@ -1,298 +0,0 @@
-// 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.
-
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// protoc-gen-go v1.27.1
-// protoc v3.17.3
-// source: banyandb/model/v2/write.proto
-
-package v2
-
-import (
- reflect "reflect"
- sync "sync"
-
- protoreflect "google.golang.org/protobuf/reflect/protoreflect"
- protoimpl "google.golang.org/protobuf/runtime/protoimpl"
- structpb "google.golang.org/protobuf/types/known/structpb"
-)
-
-const (
- // Verify that this generated code is sufficiently up-to-date.
- _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
- // Verify that runtime/protoimpl is sufficiently up-to-date.
- _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-type Tag struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- // Types that are assignable to ValueType:
- // *Tag_Null
- // *Tag_Str
- // *Tag_StrArray
- // *Tag_Int
- // *Tag_IntArray
- // *Tag_BinaryData
- ValueType isTag_ValueType `protobuf_oneof:"value_type"`
-}
-
-func (x *Tag) Reset() {
- *x = Tag{}
- if protoimpl.UnsafeEnabled {
- mi := &file_banyandb_model_v2_write_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *Tag) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Tag) ProtoMessage() {}
-
-func (x *Tag) ProtoReflect() protoreflect.Message {
- mi := &file_banyandb_model_v2_write_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use Tag.ProtoReflect.Descriptor instead.
-func (*Tag) Descriptor() ([]byte, []int) {
- return file_banyandb_model_v2_write_proto_rawDescGZIP(), []int{0}
-}
-
-func (m *Tag) GetValueType() isTag_ValueType {
- if m != nil {
- return m.ValueType
- }
- return nil
-}
-
-func (x *Tag) GetNull() structpb.NullValue {
- if x, ok := x.GetValueType().(*Tag_Null); ok {
- return x.Null
- }
- return structpb.NullValue(0)
-}
-
-func (x *Tag) GetStr() *Str {
- if x, ok := x.GetValueType().(*Tag_Str); ok {
- return x.Str
- }
- return nil
-}
-
-func (x *Tag) GetStrArray() *StrArray {
- if x, ok := x.GetValueType().(*Tag_StrArray); ok {
- return x.StrArray
- }
- return nil
-}
-
-func (x *Tag) GetInt() *Int {
- if x, ok := x.GetValueType().(*Tag_Int); ok {
- return x.Int
- }
- return nil
-}
-
-func (x *Tag) GetIntArray() *IntArray {
- if x, ok := x.GetValueType().(*Tag_IntArray); ok {
- return x.IntArray
- }
- return nil
-}
-
-func (x *Tag) GetBinaryData() []byte {
- if x, ok := x.GetValueType().(*Tag_BinaryData); ok {
- return x.BinaryData
- }
- return nil
-}
-
-type isTag_ValueType interface {
- isTag_ValueType()
-}
-
-type Tag_Null struct {
- Null structpb.NullValue `protobuf:"varint,1,opt,name=null,proto3,enum=google.protobuf.NullValue,oneof"`
-}
-
-type Tag_Str struct {
- Str *Str `protobuf:"bytes,2,opt,name=str,proto3,oneof"`
-}
-
-type Tag_StrArray struct {
- StrArray *StrArray `protobuf:"bytes,3,opt,name=str_array,json=strArray,proto3,oneof"`
-}
-
-type Tag_Int struct {
- Int *Int `protobuf:"bytes,4,opt,name=int,proto3,oneof"`
-}
-
-type Tag_IntArray struct {
- IntArray *IntArray `protobuf:"bytes,5,opt,name=int_array,json=intArray,proto3,oneof"`
-}
-
-type Tag_BinaryData struct {
- BinaryData []byte `protobuf:"bytes,6,opt,name=binary_data,json=binaryData,proto3,oneof"`
-}
-
-func (*Tag_Null) isTag_ValueType() {}
-
-func (*Tag_Str) isTag_ValueType() {}
-
-func (*Tag_StrArray) isTag_ValueType() {}
-
-func (*Tag_Int) isTag_ValueType() {}
-
-func (*Tag_IntArray) isTag_ValueType() {}
-
-func (*Tag_BinaryData) isTag_ValueType() {}
-
-var File_banyandb_model_v2_write_proto protoreflect.FileDescriptor
-
-var file_banyandb_model_v2_write_proto_rawDesc = []byte{
- 0x0a, 0x1d, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
- 0x2f, 0x76, 0x32, 0x2f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
- 0x11, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e,
- 0x76, 0x32, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x1a, 0x1e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
- 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x22, 0xb8, 0x02, 0x0a, 0x03, 0x54, 0x61, 0x67, 0x12, 0x30, 0x0a, 0x04, 0x6e, 0x75, 0x6c, 0x6c,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4e, 0x75, 0x6c, 0x6c, 0x56, 0x61, 0x6c,
- 0x75, 0x65, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x75, 0x6c, 0x6c, 0x12, 0x2a, 0x0a, 0x03, 0x73, 0x74,
- 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e,
- 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x72, 0x48,
- 0x00, 0x52, 0x03, 0x73, 0x74, 0x72, 0x12, 0x3a, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x5f, 0x61, 0x72,
- 0x72, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79,
- 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74,
- 0x72, 0x41, 0x72, 0x72, 0x61, 0x79, 0x48, 0x00, 0x52, 0x08, 0x73, 0x74, 0x72, 0x41, 0x72, 0x72,
- 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x03, 0x69, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x16, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
- 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x03, 0x69, 0x6e, 0x74, 0x12, 0x3a,
- 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64,
- 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x49, 0x6e, 0x74, 0x41, 0x72, 0x72, 0x61, 0x79, 0x48, 0x00,
- 0x52, 0x08, 0x69, 0x6e, 0x74, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x21, 0x0a, 0x0b, 0x62, 0x69,
- 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x48,
- 0x00, 0x52, 0x0a, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61, 0x42, 0x0c, 0x0a,
- 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x6c, 0x0a, 0x27, 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, 0x6d, 0x6f,
- 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x5a, 0x41, 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, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x33,
-}
-
-var (
- file_banyandb_model_v2_write_proto_rawDescOnce sync.Once
- file_banyandb_model_v2_write_proto_rawDescData = file_banyandb_model_v2_write_proto_rawDesc
-)
-
-func file_banyandb_model_v2_write_proto_rawDescGZIP() []byte {
- file_banyandb_model_v2_write_proto_rawDescOnce.Do(func() {
- file_banyandb_model_v2_write_proto_rawDescData = protoimpl.X.CompressGZIP(file_banyandb_model_v2_write_proto_rawDescData)
- })
- return file_banyandb_model_v2_write_proto_rawDescData
-}
-
-var file_banyandb_model_v2_write_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_banyandb_model_v2_write_proto_goTypes = []interface{}{
- (*Tag)(nil), // 0: banyandb.model.v2.Tag
- (structpb.NullValue)(0), // 1: google.protobuf.NullValue
- (*Str)(nil), // 2: banyandb.model.v2.Str
- (*StrArray)(nil), // 3: banyandb.model.v2.StrArray
- (*Int)(nil), // 4: banyandb.model.v2.Int
- (*IntArray)(nil), // 5: banyandb.model.v2.IntArray
-}
-var file_banyandb_model_v2_write_proto_depIdxs = []int32{
- 1, // 0: banyandb.model.v2.Tag.null:type_name -> google.protobuf.NullValue
- 2, // 1: banyandb.model.v2.Tag.str:type_name -> banyandb.model.v2.Str
- 3, // 2: banyandb.model.v2.Tag.str_array:type_name -> banyandb.model.v2.StrArray
- 4, // 3: banyandb.model.v2.Tag.int:type_name -> banyandb.model.v2.Int
- 5, // 4: banyandb.model.v2.Tag.int_array:type_name -> banyandb.model.v2.IntArray
- 5, // [5:5] is the sub-list for method output_type
- 5, // [5:5] is the sub-list for method input_type
- 5, // [5:5] is the sub-list for extension type_name
- 5, // [5:5] is the sub-list for extension extendee
- 0, // [0:5] is the sub-list for field type_name
-}
-
-func init() { file_banyandb_model_v2_write_proto_init() }
-func file_banyandb_model_v2_write_proto_init() {
- if File_banyandb_model_v2_write_proto != nil {
- return
- }
- file_banyandb_model_v2_common_proto_init()
- if !protoimpl.UnsafeEnabled {
- file_banyandb_model_v2_write_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Tag); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- }
- file_banyandb_model_v2_write_proto_msgTypes[0].OneofWrappers = []interface{}{
- (*Tag_Null)(nil),
- (*Tag_Str)(nil),
- (*Tag_StrArray)(nil),
- (*Tag_Int)(nil),
- (*Tag_IntArray)(nil),
- (*Tag_BinaryData)(nil),
- }
- type x struct{}
- out := protoimpl.TypeBuilder{
- File: protoimpl.DescBuilder{
- GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_banyandb_model_v2_write_proto_rawDesc,
- NumEnums: 0,
- NumMessages: 1,
- NumExtensions: 0,
- NumServices: 0,
- },
- GoTypes: file_banyandb_model_v2_write_proto_goTypes,
- DependencyIndexes: file_banyandb_model_v2_write_proto_depIdxs,
- MessageInfos: file_banyandb_model_v2_write_proto_msgTypes,
- }.Build()
- File_banyandb_model_v2_write_proto = out.File
- file_banyandb_model_v2_write_proto_rawDesc = nil
- file_banyandb_model_v2_write_proto_goTypes = nil
- file_banyandb_model_v2_write_proto_depIdxs = nil
-}
diff --git a/api/proto/banyandb/stream/v2/query.pb.go b/api/proto/banyandb/stream/v2/query.pb.go
index 9a3d1e1..5ad9ae1 100644
--- a/api/proto/banyandb/stream/v2/query.pb.go
+++ b/api/proto/banyandb/stream/v2/query.pb.go
@@ -56,15 +56,13 @@ type Element struct {
// 1) either the start time of a Span/Segment,
// 2) or the timestamp of a log
Timestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
- // data_binary contains all un-indexed Tags and other key-value pairs
- DataBinary []byte `protobuf:"bytes,3,opt,name=data_binary,json=dataBinary,proto3" json:"data_binary,omitempty"`
// fields contains all indexed Field. Some typical names,
// - stream_id
// - duration
// - service_name
// - service_instance_id
// - end_time_nanoseconds
- Tags []*v2.TypedPair `protobuf:"bytes,4,rep,name=tags,proto3" json:"tags,omitempty"`
+ TagFamilies []*v2.TagFamily `protobuf:"bytes,3,rep,name=tag_families,json=tagFamilies,proto3" json:"tag_families,omitempty"`
}
func (x *Element) Reset() {
@@ -113,16 +111,9 @@ func (x *Element) GetTimestamp() *timestamppb.Timestamp {
return nil
}
-func (x *Element) GetDataBinary() []byte {
+func (x *Element) GetTagFamilies() []*v2.TagFamily {
if x != nil {
- return x.DataBinary
- }
- return nil
-}
-
-func (x *Element) GetTags() []*v2.TypedPair {
- if x != nil {
- return x.Tags
+ return x.TagFamilies
}
return nil
}
@@ -194,9 +185,8 @@ type QueryRequest struct {
// limit is used to impose a boundary on the number of records being returned
Limit uint32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"`
// order_by is given to specify the sort for a field. So far, only fields in the type of Integer are supported
- OrderBy *v2.QueryOrder `protobuf:"bytes,5,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"`
- // tags are indexed. Some typical tags are listed below,
- Tags []*v2.PairQuery `protobuf:"bytes,6,rep,name=tags,proto3" json:"tags,omitempty"`
+ OrderBy *v2.QueryOrder `protobuf:"bytes,5,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"`
+ Criteria []*QueryRequest_Criteria `protobuf:"bytes,6,rep,name=criteria,proto3" json:"criteria,omitempty"`
// projection can be used to select the key names of the element in the response
Projection *v2.Projection `protobuf:"bytes,7,opt,name=projection,proto3" json:"projection,omitempty"`
}
@@ -268,9 +258,9 @@ func (x *QueryRequest) GetOrderBy() *v2.QueryOrder {
return nil
}
-func (x *QueryRequest) GetTags() []*v2.PairQuery {
+func (x *QueryRequest) GetCriteria() []*QueryRequest_Criteria {
if x != nil {
- return x.Tags
+ return x.Criteria
}
return nil
}
@@ -282,6 +272,62 @@ func (x *QueryRequest) GetProjection() *v2.Projection {
return nil
}
+// tag_families are indexed.
+type QueryRequest_Criteria struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ TagFamilyName string `protobuf:"bytes,1,opt,name=tag_family_name,json=tagFamilyName,proto3" json:"tag_family_name,omitempty"`
+ Conditions []*v2.Condition `protobuf:"bytes,2,rep,name=conditions,proto3" json:"conditions,omitempty"`
+}
+
+func (x *QueryRequest_Criteria) Reset() {
+ *x = QueryRequest_Criteria{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_banyandb_stream_v2_query_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *QueryRequest_Criteria) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*QueryRequest_Criteria) ProtoMessage() {}
+
+func (x *QueryRequest_Criteria) ProtoReflect() protoreflect.Message {
+ mi := &file_banyandb_stream_v2_query_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use QueryRequest_Criteria.ProtoReflect.Descriptor instead.
+func (*QueryRequest_Criteria) Descriptor() ([]byte, []int) {
+ return file_banyandb_stream_v2_query_proto_rawDescGZIP(), []int{2, 0}
+}
+
+func (x *QueryRequest_Criteria) GetTagFamilyName() string {
+ if x != nil {
+ return x.TagFamilyName
+ }
+ return ""
+}
+
+func (x *QueryRequest_Criteria) GetConditions() []*v2.Condition {
+ if x != nil {
+ return x.Conditions
+ }
+ return nil
+}
+
var File_banyandb_stream_v2_query_proto protoreflect.FileDescriptor
var file_banyandb_stream_v2_query_proto_rawDesc = []byte{
@@ -294,52 +340,60 @@ var file_banyandb_stream_v2_query_proto_rawDesc = []byte{
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62,
0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x2f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb5, 0x01, 0x0a, 0x07, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa3, 0x01, 0x0a, 0x07, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64,
0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 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, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61,
- 0x74, 0x61, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52,
- 0x0a, 0x64, 0x61, 0x74, 0x61, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x74,
- 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79,
- 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x79,
- 0x70, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0x48, 0x0a,
- 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37,
- 0x0a, 0x08, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x73, 0x74, 0x72, 0x65,
- 0x61, 0x6d, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x65,
- 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xde, 0x02, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72,
- 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x3b, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64,
- 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52,
- 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12,
- 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
- 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x38, 0x0a,
- 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x1d, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
- 0x2e, 0x76, 0x32, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x07,
- 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18,
- 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62,
- 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x51, 0x75,
- 0x65, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x3d, 0x0a, 0x0a, 0x70, 0x72, 0x6f,
- 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
+ 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0c, 0x74, 0x61,
+ 0x67, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65,
+ 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x52, 0x0b,
+ 0x74, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x22, 0x48, 0x0a, 0x0d, 0x51,
+ 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x08,
+ 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b,
+ 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
+ 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xe5, 0x03, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x3b, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e,
+ 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e,
+ 0x67, 0x65, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x16, 0x0a,
+ 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6f,
+ 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x08, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e,
0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76,
- 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x70, 0x72,
- 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x6e, 0x0a, 0x28, 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, 0x73, 0x74, 0x72, 0x65, 0x61,
- 0x6d, 0x2e, 0x76, 0x32, 0x5a, 0x42, 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, 0x73,
- 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x32, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x07, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x42, 0x79, 0x12, 0x45, 0x0a, 0x08, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69,
+ 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e,
+ 0x64, 0x62, 0x2e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x32, 0x2e, 0x51, 0x75, 0x65,
+ 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x65, 0x72,
+ 0x69, 0x61, 0x52, 0x08, 0x63, 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x3d, 0x0a, 0x0a,
+ 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1d, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65,
+ 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+ 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x70, 0x0a, 0x08, 0x43,
+ 0x72, 0x69, 0x74, 0x65, 0x72, 0x69, 0x61, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x61, 0x67, 0x5f, 0x66,
+ 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0d, 0x74, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+ 0x3c, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d,
+ 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x6e, 0x0a,
+ 0x28, 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,
+ 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x32, 0x5a, 0x42, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -354,33 +408,35 @@ func file_banyandb_stream_v2_query_proto_rawDescGZIP() []byte {
return file_banyandb_stream_v2_query_proto_rawDescData
}
-var file_banyandb_stream_v2_query_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_banyandb_stream_v2_query_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_banyandb_stream_v2_query_proto_goTypes = []interface{}{
(*Element)(nil), // 0: banyandb.stream.v2.Element
(*QueryResponse)(nil), // 1: banyandb.stream.v2.QueryResponse
(*QueryRequest)(nil), // 2: banyandb.stream.v2.QueryRequest
- (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp
- (*v2.TypedPair)(nil), // 4: banyandb.model.v2.TypedPair
- (*v21.Metadata)(nil), // 5: banyandb.common.v2.Metadata
- (*v2.TimeRange)(nil), // 6: banyandb.model.v2.TimeRange
- (*v2.QueryOrder)(nil), // 7: banyandb.model.v2.QueryOrder
- (*v2.PairQuery)(nil), // 8: banyandb.model.v2.PairQuery
+ (*QueryRequest_Criteria)(nil), // 3: banyandb.stream.v2.QueryRequest.Criteria
+ (*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
+ (*v2.TagFamily)(nil), // 5: banyandb.model.v2.TagFamily
+ (*v21.Metadata)(nil), // 6: banyandb.common.v2.Metadata
+ (*v2.TimeRange)(nil), // 7: banyandb.model.v2.TimeRange
+ (*v2.QueryOrder)(nil), // 8: banyandb.model.v2.QueryOrder
(*v2.Projection)(nil), // 9: banyandb.model.v2.Projection
+ (*v2.Condition)(nil), // 10: banyandb.model.v2.Condition
}
var file_banyandb_stream_v2_query_proto_depIdxs = []int32{
- 3, // 0: banyandb.stream.v2.Element.timestamp:type_name -> google.protobuf.Timestamp
- 4, // 1: banyandb.stream.v2.Element.tags:type_name -> banyandb.model.v2.TypedPair
- 0, // 2: banyandb.stream.v2.QueryResponse.elements:type_name -> banyandb.stream.v2.Element
- 5, // 3: banyandb.stream.v2.QueryRequest.metadata:type_name -> banyandb.common.v2.Metadata
- 6, // 4: banyandb.stream.v2.QueryRequest.time_range:type_name -> banyandb.model.v2.TimeRange
- 7, // 5: banyandb.stream.v2.QueryRequest.order_by:type_name -> banyandb.model.v2.QueryOrder
- 8, // 6: banyandb.stream.v2.QueryRequest.tags:type_name -> banyandb.model.v2.PairQuery
- 9, // 7: banyandb.stream.v2.QueryRequest.projection:type_name -> banyandb.model.v2.Projection
- 8, // [8:8] is the sub-list for method output_type
- 8, // [8:8] is the sub-list for method input_type
- 8, // [8:8] is the sub-list for extension type_name
- 8, // [8:8] is the sub-list for extension extendee
- 0, // [0:8] is the sub-list for field type_name
+ 4, // 0: banyandb.stream.v2.Element.timestamp:type_name -> google.protobuf.Timestamp
+ 5, // 1: banyandb.stream.v2.Element.tag_families:type_name -> banyandb.model.v2.TagFamily
+ 0, // 2: banyandb.stream.v2.QueryResponse.elements:type_name -> banyandb.stream.v2.Element
+ 6, // 3: banyandb.stream.v2.QueryRequest.metadata:type_name -> banyandb.common.v2.Metadata
+ 7, // 4: banyandb.stream.v2.QueryRequest.time_range:type_name -> banyandb.model.v2.TimeRange
+ 8, // 5: banyandb.stream.v2.QueryRequest.order_by:type_name -> banyandb.model.v2.QueryOrder
+ 3, // 6: banyandb.stream.v2.QueryRequest.criteria:type_name -> banyandb.stream.v2.QueryRequest.Criteria
+ 9, // 7: banyandb.stream.v2.QueryRequest.projection:type_name -> banyandb.model.v2.Projection
+ 10, // 8: banyandb.stream.v2.QueryRequest.Criteria.conditions:type_name -> banyandb.model.v2.Condition
+ 9, // [9:9] is the sub-list for method output_type
+ 9, // [9:9] is the sub-list for method input_type
+ 9, // [9:9] is the sub-list for extension type_name
+ 9, // [9:9] is the sub-list for extension extendee
+ 0, // [0:9] is the sub-list for field type_name
}
func init() { file_banyandb_stream_v2_query_proto_init() }
@@ -425,6 +481,18 @@ func file_banyandb_stream_v2_query_proto_init() {
return nil
}
}
+ file_banyandb_stream_v2_query_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*QueryRequest_Criteria); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -432,7 +500,7 @@ func file_banyandb_stream_v2_query_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_banyandb_stream_v2_query_proto_rawDesc,
NumEnums: 0,
- NumMessages: 3,
+ NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/api/proto/banyandb/stream/v2/query.proto b/api/proto/banyandb/stream/v2/query.proto
index e351a45..530de48 100644
--- a/api/proto/banyandb/stream/v2/query.proto
+++ b/api/proto/banyandb/stream/v2/query.proto
@@ -36,15 +36,13 @@ message Element {
// 1) either the start time of a Span/Segment,
// 2) or the timestamp of a log
google.protobuf.Timestamp timestamp = 2;
- // data_binary contains all un-indexed Tags and other key-value pairs
- bytes data_binary = 3;
// fields contains all indexed Field. Some typical names,
// - stream_id
// - duration
// - service_name
// - service_instance_id
// - end_time_nanoseconds
- repeated model.v2.TypedPair tags = 4;
+ repeated model.v2.TagFamily tag_families = 3;
}
// QueryResponse is the response for a query to the Query module.
@@ -68,8 +66,12 @@ message QueryRequest {
uint32 limit = 4;
// order_by is given to specify the sort for a field. So far, only fields in the type of Integer are supported
model.v2.QueryOrder order_by = 5;
- // tags are indexed. Some typical tags are listed below,
- repeated model.v2.PairQuery tags = 6;
+ // tag_families are indexed.
+ message Criteria {
+ string tag_family_name = 1;
+ repeated model.v2.Condition conditions = 2;
+ }
+ repeated Criteria criteria = 6;
// projection can be used to select the key names of the element in the response
model.v2.Projection projection = 7;
}
diff --git a/api/proto/banyandb/stream/v2/write.pb.go b/api/proto/banyandb/stream/v2/write.pb.go
index ecc7655..608436d 100644
--- a/api/proto/banyandb/stream/v2/write.pb.go
+++ b/api/proto/banyandb/stream/v2/write.pb.go
@@ -210,7 +210,7 @@ type ElementValue_TagFamily struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- Tags []*v21.Tag `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty"`
+ Tags []*v21.TagValue `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty"`
}
func (x *ElementValue_TagFamily) Reset() {
@@ -245,7 +245,7 @@ func (*ElementValue_TagFamily) Descriptor() ([]byte, []int) {
return file_banyandb_stream_v2_write_proto_rawDescGZIP(), []int{0, 0}
}
-func (x *ElementValue_TagFamily) GetTags() []*v21.Tag {
+func (x *ElementValue_TagFamily) GetTags() []*v21.TagValue {
if x != nil {
return x.Tags
}
@@ -262,41 +262,41 @@ var file_banyandb_stream_v2_write_proto_rawDesc = []byte{
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2f,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62,
- 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x2f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xef, 0x01, 0x0a, 0x0c, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
- 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e,
- 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6c, 0x65, 0x6d,
- 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
- 0x6d, 0x70, 0x18, 0x02, 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, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12,
- 0x4d, 0x0a, 0x0c, 0x74, 0x61, 0x67, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x18,
- 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62,
- 0x2e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6c, 0x65, 0x6d, 0x65,
- 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c,
- 0x79, 0x52, 0x0b, 0x74, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x1a, 0x37,
- 0x0a, 0x09, 0x54, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x2a, 0x0a, 0x04, 0x74,
- 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x61, 0x6e, 0x79,
- 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54, 0x61,
- 0x67, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0x84, 0x01, 0x0a, 0x0c, 0x57, 0x72, 0x69, 0x74,
- 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x3a, 0x0a, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x73,
- 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x0f,
- 0x0a, 0x0d, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
- 0x6e, 0x0a, 0x28, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x32, 0x5a, 0x42, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2f, 0x76, 0x32, 0x62,
- 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64, 0x62,
+ 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf4, 0x01, 0x0a, 0x0c, 0x45, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6c, 0x65, 0x6d, 0x65,
+ 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
+ 0x61, 0x6d, 0x70, 0x18, 0x02, 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, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ 0x12, 0x4d, 0x0a, 0x0c, 0x74, 0x61, 0x67, 0x5f, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73,
+ 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x62, 0x61, 0x6e, 0x79, 0x61, 0x6e, 0x64,
+ 0x62, 0x2e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x32, 0x2e, 0x45, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69,
+ 0x6c, 0x79, 0x52, 0x0b, 0x74, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x1a,
+ 0x3c, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x2f, 0x0a, 0x04,
+ 0x74, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x62, 0x61, 0x6e,
+ 0x79, 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x76, 0x32, 0x2e, 0x54,
+ 0x61, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x22, 0x84, 0x01,
+ 0x0a, 0x0c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 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, 0x3a, 0x0a, 0x07, 0x65, 0x6c, 0x65, 0x6d,
+ 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x62, 0x61, 0x6e, 0x79,
+ 0x61, 0x6e, 0x64, 0x62, 0x2e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x32, 0x2e, 0x45,
+ 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x65, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x0f, 0x0a, 0x0d, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73,
+ 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6e, 0x0a, 0x28, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76,
+ 0x32, 0x5a, 0x42, 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, 0x73, 0x74, 0x72, 0x65,
+ 0x61, 0x6d, 0x2f, 0x76, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -319,14 +319,14 @@ var file_banyandb_stream_v2_write_proto_goTypes = []interface{}{
(*ElementValue_TagFamily)(nil), // 3: banyandb.stream.v2.ElementValue.TagFamily
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
(*v2.Metadata)(nil), // 5: banyandb.common.v2.Metadata
- (*v21.Tag)(nil), // 6: banyandb.model.v2.Tag
+ (*v21.TagValue)(nil), // 6: banyandb.model.v2.TagValue
}
var file_banyandb_stream_v2_write_proto_depIdxs = []int32{
4, // 0: banyandb.stream.v2.ElementValue.timestamp:type_name -> google.protobuf.Timestamp
3, // 1: banyandb.stream.v2.ElementValue.tag_families:type_name -> banyandb.stream.v2.ElementValue.TagFamily
5, // 2: banyandb.stream.v2.WriteRequest.metadata:type_name -> banyandb.common.v2.Metadata
0, // 3: banyandb.stream.v2.WriteRequest.element:type_name -> banyandb.stream.v2.ElementValue
- 6, // 4: banyandb.stream.v2.ElementValue.TagFamily.tags:type_name -> banyandb.model.v2.Tag
+ 6, // 4: banyandb.stream.v2.ElementValue.TagFamily.tags:type_name -> banyandb.model.v2.TagValue
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
diff --git a/api/proto/banyandb/stream/v2/write.proto b/api/proto/banyandb/stream/v2/write.proto
index 39ef649..c845dbc 100644
--- a/api/proto/banyandb/stream/v2/write.proto
+++ b/api/proto/banyandb/stream/v2/write.proto
@@ -24,9 +24,7 @@ package banyandb.stream.v2;
import "google/protobuf/timestamp.proto";
import "banyandb/common/v2/common.proto";
-import "banyandb/model/v2/write.proto";
-
-
+import "banyandb/model/v2/common.proto";
message ElementValue {
// element_id could be span_id of a Span or segment_id of a Segment in the context of stream
@@ -36,7 +34,7 @@ message ElementValue {
// 2) or the timestamp of a log
google.protobuf.Timestamp timestamp = 2;
message TagFamily {
- repeated model.v2.Tag tags = 1;
+ repeated model.v2.TagValue tags = 1;
}
// the order of tag_families' items match the stream schema
repeated TagFamily tag_families = 3;
diff --git a/banyand/index/tsdb/field_map.go b/banyand/index/tsdb/field_map.go
index 4d89713..6cc52f8 100644
--- a/banyand/index/tsdb/field_map.go
+++ b/banyand/index/tsdb/field_map.go
@@ -53,7 +53,7 @@ func (fm *fieldMap) get(key []byte) (*fieldValue, bool) {
func (fm *fieldMap) put(fv *Field, id common.ChunkID) error {
pm, ok := fm.get(fv.Name)
if !ok {
- return errors.Wrapf(ErrFieldAbsent, "filed Name:%s", fv.Name)
+ return errors.Wrapf(ErrFieldAbsent, "filed Term:%s", fv.Name)
}
return pm.value.put(fv.Value, id)
}
diff --git a/banyand/kv/badger.go b/banyand/kv/badger.go
index 8a35c29..0dfbbe7 100644
--- a/banyand/kv/badger.go
+++ b/banyand/kv/badger.go
@@ -27,9 +27,13 @@ import (
"github.com/dgraph-io/badger/v3/y"
"go.uber.org/multierr"
+ modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting/roaring"
"github.com/apache/skywalking-banyandb/pkg/logger"
- "github.com/apache/skywalking-banyandb/pkg/posting"
- "github.com/apache/skywalking-banyandb/pkg/posting/roaring"
+ posting2 "github.com/apache/skywalking-banyandb/pkg/posting"
+ roaring2 "github.com/apache/skywalking-banyandb/pkg/posting/roaring"
)
var (
@@ -56,7 +60,7 @@ func (b *badgerTSS) Close() error {
}
type mergedIter struct {
- delegated Iterator
+ delegated Iterator2
valid bool
data []byte
}
@@ -116,26 +120,26 @@ type badgerDB struct {
db *badger.DB
}
-func (b *badgerDB) Handover(iterator Iterator) error {
+func (b *badgerDB) Handover(iterator Iterator2) error {
return b.db.HandoverIterator(&mergedIter{
delegated: iterator,
})
}
-func (b *badgerDB) Seek(key []byte, limit int) (posting.List, error) {
+func (b *badgerDB) Seek(key []byte, limit int) (posting2.List, error) {
opts := badger.DefaultIteratorOptions
it := b.db.NewIterator(opts)
defer func() {
_ = it.Close()
}()
- result := roaring.NewPostingList()
+ result := roaring2.NewPostingList()
var errMerged error
for it.Seek(y.KeyWithTs(key, math.MaxInt64)); it.Valid(); it.Next() {
k := y.ParseKey(it.Key())
if !bytes.Equal(key, k) {
break
}
- list := roaring.NewPostingList()
+ list := roaring2.NewPostingList()
err := list.Unmarshall(it.Value().Value)
if err != nil {
errMerged = multierr.Append(errMerged, err)
@@ -153,6 +157,7 @@ func (b *badgerDB) Scan(key []byte, opt ScanOpts, f ScanFunc) error {
opts := badger.DefaultIteratorOptions
opts.PrefetchSize = opt.PrefetchSize
opts.PrefetchValues = opt.PrefetchValues
+ opts.Reverse = opt.Reverse
it := b.db.NewIterator(opts)
defer func() {
_ = it.Close()
@@ -172,6 +177,56 @@ func (b *badgerDB) Scan(key []byte, opt ScanOpts, f ScanFunc) error {
return nil
}
+var _ Iterator = (*iterator)(nil)
+
+type iterator struct {
+ delegated y.Iterator
+}
+
+func (i *iterator) Next() {
+ i.delegated.Next()
+}
+
+func (i *iterator) Rewind() {
+ i.delegated.Rewind()
+}
+
+func (i *iterator) Seek(key []byte) {
+ i.delegated.Seek(key)
+}
+
+func (i *iterator) Key() []byte {
+ return i.delegated.Key()
+}
+
+func (i *iterator) Val() posting.List {
+ list := roaring.NewPostingList()
+ data := make([]byte, len(i.delegated.Value().Value))
+ copy(data, i.delegated.Value().Value)
+ _ = list.Unmarshall(data)
+ return list
+}
+
+func (i *iterator) Valid() bool {
+ return i.delegated.Valid()
+}
+
+func (i *iterator) Close() error {
+ return i.delegated.Close()
+}
+
+func (b *badgerDB) NewIterator(opt ScanOpts) Iterator {
+ opts := badger.DefaultIteratorOptions
+ opts.PrefetchSize = opt.PrefetchSize
+ opts.PrefetchValues = opt.PrefetchValues
+ opts.Reverse = opt.Reverse
+ opts.Prefix = opt.Prefix
+ it := b.db.NewIterator(opts)
+ return &iterator{
+ delegated: it,
+ }
+}
+
func (b *badgerDB) Close() error {
if b.db != nil && !b.db.IsClosed() {
return b.db.Close()
@@ -183,6 +238,10 @@ func (b *badgerDB) Put(key, val []byte) error {
return b.db.Put(y.KeyWithTs(key, math.MaxInt64), val)
}
+func (b *badgerDB) PutWithVersion(key, val []byte, version uint64) error {
+ return b.db.Put(y.KeyWithTs(key, version), val)
+}
+
func (b *badgerDB) Get(key []byte) ([]byte, error) {
v, err := b.db.Get(y.KeyWithTs(key, math.MaxInt64))
if err == badger.ErrKeyNotFound {
@@ -194,6 +253,75 @@ func (b *badgerDB) Get(key []byte) ([]byte, error) {
return v.Value, nil
}
+func (b *badgerDB) GetAll(key []byte, applyFn func([]byte) error) error {
+ iter := b.db.NewIterator(badger.DefaultIteratorOptions)
+ var count int
+ for iter.Seek(key); iter.Valid(); iter.Next() {
+ count++
+ err := applyFn(y.Copy(iter.Value().Value))
+ if err != nil {
+ return err
+ }
+ }
+ if count > 0 {
+ return nil
+ }
+ return ErrKeyNotFound
+}
+
+func (b *badgerDB) MatchField(fieldName []byte) (list posting.List) {
+ panic("implement me")
+}
+
+func (b *badgerDB) MatchTerms(field index.Field) (list posting.List) {
+ panic("implement me")
+}
+
+func (b *badgerDB) Range(fieldName []byte, opts index.RangeOpts) (list posting.List) {
+ panic("implement me")
+}
+
+var _ index.FieldIterator = (*fIterator)(nil)
+
+type fIterator struct {
+ init bool
+ delegate Iterator
+}
+
+func (f *fIterator) Next() bool {
+ if f.init {
+ f.delegate.Next()
+ } else {
+ f.init = true
+ }
+ return f.delegate.Valid()
+}
+
+func (f *fIterator) Val() *index.PostingValue {
+ return &index.PostingValue{
+ Key: f.delegate.Key(),
+ Value: f.delegate.Val(),
+ }
+}
+
+func (f *fIterator) Close() error {
+ return f.delegate.Close()
+}
+
+func (b *badgerDB) FieldIterator(fieldName []byte, order modelv2.QueryOrder_Sort) index.FieldIterator {
+ var reverse bool
+ if order == modelv2.QueryOrder_SORT_DESC {
+ reverse = true
+ }
+ iter := b.NewIterator(ScanOpts{
+ Prefix: fieldName,
+ Reverse: reverse,
+ })
+ return &fIterator{
+ delegate: iter,
+ }
+}
+
// badgerLog delegates the zap log to the badger logger
type badgerLog struct {
*log.Logger
diff --git a/banyand/kv/kv.go b/banyand/kv/kv.go
index ccaa8be..5cea6ed 100644
--- a/banyand/kv/kv.go
+++ b/banyand/kv/kv.go
@@ -20,12 +20,15 @@ package kv
import (
"fmt"
"io"
+ "math"
"github.com/dgraph-io/badger/v3"
"github.com/pkg/errors"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
"github.com/apache/skywalking-banyandb/pkg/logger"
- "github.com/apache/skywalking-banyandb/pkg/posting"
+ posting2 "github.com/apache/skywalking-banyandb/pkg/posting"
)
var (
@@ -39,6 +42,7 @@ var (
type Writer interface {
// Put a value
Put(key, val []byte) error
+ PutWithVersion(key, val []byte, version uint64) error
}
type ScanFunc func(shardID int, key []byte, getVal func() ([]byte, error)) error
@@ -46,11 +50,14 @@ type ScanFunc func(shardID int, key []byte, getVal func() ([]byte, error)) error
type ScanOpts struct {
PrefetchSize int
PrefetchValues bool
+ Reverse bool
+ Prefix []byte
}
type Reader interface {
// Get a value by its key
Get(key []byte) ([]byte, error)
+ GetAll(key []byte, applyFn func([]byte) error) error
Scan(prefix []byte, opt ScanOpts, f ScanFunc) error
}
@@ -59,6 +66,7 @@ type Store interface {
io.Closer
Writer
Reader
+ index.Searcher
}
type TimeSeriesWriter interface {
@@ -106,11 +114,21 @@ type Iterator interface {
Close() error
}
+type Iterator2 interface {
+ Next()
+ Rewind()
+ Seek(key []byte)
+ Key() []byte
+ Val() posting2.List
+ Valid() bool
+ Close() error
+}
+
type HandoverCallback func()
type IndexStore interface {
- Handover(iterator Iterator) error
- Seek(key []byte, limit int) (posting.List, error)
+ Handover(iterator Iterator2) error
+ Seek(key []byte, limit int) (posting2.List, error)
Close() error
}
@@ -180,7 +198,8 @@ func OpenStore(shardID int, path string, options ...StoreOptions) (Store, error)
for _, opt := range options {
opt(bdb)
}
- bdb.dbOpts = bdb.dbOpts.WithMaxLevels(1)
+ bdb.dbOpts = bdb.dbOpts.WithMaxLevels(2)
+ bdb.dbOpts = bdb.dbOpts.WithNumVersionsToKeep(math.MaxUint32)
var err error
bdb.db, err = badger.Open(bdb.dbOpts)
@@ -211,9 +230,8 @@ func OpenIndexStore(shardID int, path string, options ...IndexOptions) (IndexSto
for _, opt := range options {
opt(bdb)
}
- bdb.dbOpts = bdb.dbOpts.WithMaxLevels(1)
- // Put all values into LSM
- bdb.dbOpts = bdb.dbOpts.WithVLogPercentile(1.0)
+ bdb.dbOpts = bdb.dbOpts.WithMaxLevels(2)
+ bdb.dbOpts = bdb.dbOpts.WithNumVersionsToKeep(math.MaxUint32)
var err error
bdb.db, err = badger.Open(bdb.dbOpts)
diff --git a/banyand/storage/database_test.go b/banyand/storage/database_test.go
index 89c910e..971cdf7 100644
--- a/banyand/storage/database_test.go
+++ b/banyand/storage/database_test.go
@@ -168,7 +168,7 @@ func TestDB_FlushCallback(t *testing.T) {
}
}
-var _ kv.Iterator = (*iter)(nil)
+var _ kv.Iterator2 = (*iter)(nil)
type iter struct {
data map[int]posting.List
@@ -204,7 +204,7 @@ func (i *iter) Close() error {
return nil
}
-func mockMemtable(data ...[]uint64) kv.Iterator {
+func mockMemtable(data ...[]uint64) kv.Iterator2 {
it := &iter{
data: make(map[int]posting.List),
}
diff --git a/banyand/stream/index.go b/banyand/stream/index.go
index 1d9a463..cfbf8e9 100644
--- a/banyand/stream/index.go
+++ b/banyand/stream/index.go
@@ -22,9 +22,11 @@ import (
"go.uber.org/multierr"
+ "github.com/apache/skywalking-banyandb/api/common"
databasev2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
streamv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/stream/v2"
"github.com/apache/skywalking-banyandb/banyand/tsdb"
+ "github.com/apache/skywalking-banyandb/pkg/index"
"github.com/apache/skywalking-banyandb/pkg/partition"
)
@@ -60,7 +62,7 @@ func (s *stream) bootIndexGenerator() {
}
//TODO: should listen to pipeline in a distributed cluster
-func (s *stream) writeGlobalIndex(ruleIndex indexRule, ref tsdb.ItemID, value *streamv2.ElementValue) error {
+func (s *stream) writeGlobalIndex(ruleIndex indexRule, ref tsdb.GlobalItemID, value *streamv2.ElementValue) error {
val, err := getIndexValue(ruleIndex, value)
if err != nil {
return err
@@ -69,11 +71,11 @@ func (s *stream) writeGlobalIndex(ruleIndex indexRule, ref tsdb.ItemID, value *s
if err != nil {
return err
}
- shard, err := s.db.Shard(indexShardID)
+ shard, err := s.db.Shard(common.ShardID(indexShardID))
if err != nil {
return err
}
- builder := shard.Index().IndexWriterBuilder()
+ builder := shard.Index().WriterBuilder()
indexWriter, err := builder.
GlobalItemID(ref).
Time(value.GetTimestamp().AsTime()).
@@ -84,9 +86,15 @@ func (s *stream) writeGlobalIndex(ruleIndex indexRule, ref tsdb.ItemID, value *s
rule := ruleIndex.rule
switch rule.GetType() {
case databasev2.IndexRule_TYPE_INVERTED:
- return indexWriter.WriteInvertedIndex(rule.Metadata.Name, val)
+ return indexWriter.WriteInvertedIndex(index.Field{
+ Term: []byte(rule.Metadata.Name),
+ Value: val,
+ })
case databasev2.IndexRule_TYPE_TREE:
- return indexWriter.WriteLSMIndex(rule.Metadata.Name, val)
+ return indexWriter.WriteLSMIndex(index.Field{
+ Term: []byte(rule.Metadata.Name),
+ Value: val,
+ })
}
return err
}
@@ -99,9 +107,15 @@ func writeLocalIndex(writer tsdb.Writer, ruleIndex indexRule, value *streamv2.El
rule := ruleIndex.rule
switch rule.GetType() {
case databasev2.IndexRule_TYPE_INVERTED:
- return writer.WriteInvertedIndex(rule.Metadata.Name, val)
+ return writer.WriteInvertedIndex(index.Field{
+ Term: []byte(rule.Metadata.Name),
+ Value: val,
+ })
case databasev2.IndexRule_TYPE_TREE:
- return writer.WriteLSMIndex(rule.Metadata.Name, val)
+ return writer.WriteLSMIndex(index.Field{
+ Term: []byte(rule.Metadata.Name),
+ Value: val,
+ })
}
return err
}
diff --git a/banyand/stream/service.go b/banyand/stream/service.go
index d65978e..d7d1284 100644
--- a/banyand/stream/service.go
+++ b/banyand/stream/service.go
@@ -22,6 +22,7 @@ import (
"github.com/pkg/errors"
+ commonv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v2"
"github.com/apache/skywalking-banyandb/banyand/metadata"
"github.com/apache/skywalking-banyandb/banyand/metadata/schema"
"github.com/apache/skywalking-banyandb/banyand/queue"
@@ -29,12 +30,16 @@ import (
"github.com/apache/skywalking-banyandb/pkg/run"
)
-var ErrEmptyRootPath = errors.New("root path is empty")
+var (
+ ErrEmptyRootPath = errors.New("root path is empty")
+ ErrStreamNotExist = errors.New("stream doesn't exist")
+)
type Service interface {
run.PreRunner
run.Config
run.Service
+ Query
}
var _ Service = (*service)(nil)
@@ -47,6 +52,15 @@ type service struct {
root string
}
+func (s *service) Stream(stream *commonv2.Metadata) (Stream, error) {
+ sID := formatStreamID(stream.GetName(), stream.GetGroup())
+ sm, ok := s.schemaMap[sID]
+ if !ok {
+ return nil, errors.WithStack(ErrStreamNotExist)
+ }
+ return sm, nil
+}
+
func (s *service) FlagSet() *run.FlagSet {
flagS := run.NewFlagSet("storage")
flagS.StringVar(&s.root, "root-path", "/tmp", "the root path of database")
diff --git a/banyand/stream/stream.go b/banyand/stream/stream.go
index 338e1af..ffb4fc0 100644
--- a/banyand/stream/stream.go
+++ b/banyand/stream/stream.go
@@ -26,6 +26,8 @@ import (
"github.com/apache/skywalking-banyandb/pkg/logger"
)
+const strDelimiter = "\n"
+
type tagIndex struct {
family int
tag int
@@ -35,6 +37,7 @@ type indexRule struct {
rule *databasev2.IndexRule
tagIndices []tagIndex
}
+
type stream struct {
name string
group string
@@ -102,8 +105,9 @@ func openStream(root string, spec streamSpec, l *logger.Logger) (*stream, error)
db, err := tsdb.OpenDatabase(
context.WithValue(context.Background(), logger.ContextKey, l),
tsdb.DatabaseOpts{
- Location: root,
- ShardNum: sm.schema.GetShardNum(),
+ Location: root,
+ ShardNum: sm.schema.GetShardNum(),
+ IndexRules: spec.indexRules,
})
if err != nil {
return nil, err
@@ -117,19 +121,19 @@ func formatStreamID(name, group string) string {
return name + ":" + group
}
-func tagValueTypeConv(tag *modelv2.Tag) (tagType databasev2.TagType, isNull bool) {
- switch tag.GetValueType().(type) {
- case *modelv2.Tag_Int:
+func tagValueTypeConv(tagValue *modelv2.TagValue) (tagType databasev2.TagType, isNull bool) {
+ switch tagValue.GetValue().(type) {
+ case *modelv2.TagValue_Int:
return databasev2.TagType_TAG_TYPE_INT, false
- case *modelv2.Tag_Str:
+ case *modelv2.TagValue_Str:
return databasev2.TagType_TAG_TYPE_STRING, false
- case *modelv2.Tag_IntArray:
+ case *modelv2.TagValue_IntArray:
return databasev2.TagType_TAG_TYPE_INT_ARRAY, false
- case *modelv2.Tag_StrArray:
+ case *modelv2.TagValue_StrArray:
return databasev2.TagType_TAG_TYPE_STRING_ARRAY, false
- case *modelv2.Tag_BinaryData:
+ case *modelv2.TagValue_BinaryData:
return databasev2.TagType_TAG_TYPE_DATA_BINARY, false
- case *modelv2.Tag_Null:
+ case *modelv2.TagValue_Null:
return databasev2.TagType_TAG_TYPE_UNSPECIFIED, true
}
return databasev2.TagType_TAG_TYPE_UNSPECIFIED, false
diff --git a/banyand/stream/stream_query.go b/banyand/stream/stream_query.go
new file mode 100644
index 0000000..ac7d038
--- /dev/null
+++ b/banyand/stream/stream_query.go
@@ -0,0 +1,117 @@
+// 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 stream
+
+import (
+ "bytes"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/pkg/errors"
+
+ "github.com/apache/skywalking-banyandb/api/common"
+ commonv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v2"
+ databasev2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
+ modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
+ streamv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/stream/v2"
+ "github.com/apache/skywalking-banyandb/banyand/tsdb"
+ "github.com/apache/skywalking-banyandb/pkg/partition"
+)
+
+var (
+ ErrTagNotExist = errors.New("the tag doesn't exist")
+ ErrTagFamilyNotExist = errors.New("tag family doesn't exist")
+)
+
+type Query interface {
+ Stream(stream *commonv2.Metadata) (Stream, error)
+}
+
+type EqualCondition struct {
+ tag string
+ value []byte
+}
+
+type Stream interface {
+ Shards(equalConditions []EqualCondition) ([]tsdb.Shard, error)
+}
+
+var _ Stream = (*stream)(nil)
+
+func (s *stream) Shards(equalConditions []EqualCondition) ([]tsdb.Shard, error) {
+ entityItemLen := len(s.entityIndex)
+ entityItems := make([][]byte, entityItemLen)
+ var entityCount int
+ for _, ec := range equalConditions {
+ fi, ti, tag := s.findTagByName(ec.tag)
+ if tag == nil {
+ return nil, ErrTagNotExist
+ }
+ for i, eIndex := range s.entityIndex {
+ if eIndex.family == fi && eIndex.tag == ti {
+ entityItems[i] = ec.value
+ entityCount++
+ }
+ }
+ }
+ if entityCount < entityItemLen {
+ return s.db.Shards(), nil
+ }
+ shardID, err := partition.ShardID(bytes.Join(entityItems, nil), s.schema.GetShardNum())
+ if err != nil {
+ return nil, err
+ }
+ shard, err := s.db.Shard(common.ShardID(shardID))
+ if err != nil {
+ return nil, err
+ }
+ return []tsdb.Shard{shard}, nil
+}
+
+func (s *stream) ParseTagFamily(family string, item tsdb.Item) (*modelv2.TagFamily, error) {
+ familyRawBytes, err := item.Val(family)
+ if err != nil {
+ return nil, err
+ }
+ tagFamily := &streamv2.ElementValue_TagFamily{}
+ err = proto.Unmarshal(familyRawBytes, tagFamily)
+ if err != nil {
+ return nil, err
+ }
+ tags := make([]*modelv2.Tag, len(tagFamily.GetTags()))
+ var tagSpec []*databasev2.TagSpec
+ for _, tf := range s.schema.GetTagFamilies() {
+ if tf.GetName() == family {
+ tagSpec = tf.GetTags()
+ }
+ }
+ if tagSpec == nil {
+ return nil, ErrTagFamilyNotExist
+ }
+ for i, tag := range tagFamily.GetTags() {
+ tags[i] = &modelv2.Tag{
+ Key: tagSpec[i].GetName(),
+ Value: &modelv2.TagValue{
+ Value: tag.GetValue(),
+ },
+ }
+ }
+ return &modelv2.TagFamily{
+ Name: family,
+ Tags: tags,
+ }, err
+}
diff --git a/banyand/stream/stream_write.go b/banyand/stream/stream_write.go
index 7678ab8..2bcd0bf 100644
--- a/banyand/stream/stream_write.go
+++ b/banyand/stream/stream_write.go
@@ -18,9 +18,13 @@
package stream
import (
+ "bytes"
+ "strings"
+
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
+ "github.com/apache/skywalking-banyandb/api/common"
"github.com/apache/skywalking-banyandb/api/data"
modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
streamv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/stream/v2"
@@ -31,11 +35,12 @@ import (
)
var (
- ErrMalformedElement = errors.New("element is malformed")
- ErrUnsupportedTagTypeAsEntry = errors.New("the tag type can not be as an entry in an entity")
+ ErrMalformedElement = errors.New("element is malformed")
+ ErrUnsupportedTagTypeAsEntry = errors.New("the tag type can not be as an entry in an entity")
+ ErrUnsupportedTagForIndexField = errors.New("the tag type(for example, null) can not be as the index field value")
)
-func (s *stream) write(shardID uint, value *streamv2.ElementValue) error {
+func (s *stream) write(shardID common.ShardID, value *streamv2.ElementValue) error {
sm := s.schema
fLen := len(value.GetTagFamilies())
if fLen < 1 {
@@ -57,10 +62,7 @@ func (s *stream) write(shardID uint, value *streamv2.ElementValue) error {
return err
}
t := value.GetTimestamp().AsTime()
- wp, err := series.Span(tsdb.TimeRange{
- Start: t,
- Duration: 0,
- })
+ wp, err := series.Span(tsdb.NewTimeRange(t, 0))
if err != nil {
if wp != nil {
_ = wp.Close()
@@ -125,7 +127,7 @@ func getIndexValue(ruleIndex indexRule, value *streamv2.ElementValue) (val []byt
if err != nil {
return nil, errors.WithMessagef(err, "index rule:%v", ruleIndex.rule.Metadata)
}
- v, err := proto.Marshal(tag)
+ v, err := marshalIndexFieldValue(tag)
if err != nil {
return nil, err
}
@@ -134,22 +136,43 @@ func getIndexValue(ruleIndex indexRule, value *streamv2.ElementValue) (val []byt
return val, nil
}
-func (s *stream) buildEntity(value *streamv2.ElementValue) (entity tsdb.Entity, err error) {
- for _, index := range s.entityIndex {
+func marshalIndexFieldValue(tagValue *modelv2.TagValue) ([]byte, error) {
+ switch x := tagValue.GetValue().(type) {
+ case *modelv2.TagValue_Str:
+ return []byte(x.Str.GetValue()), nil
+ case *modelv2.TagValue_Int:
+ return convert.Int64ToBytes(x.Int.GetValue()), nil
+ case *modelv2.TagValue_StrArray:
+ return []byte(strings.Join(x.StrArray.GetValue(), strDelimiter)), nil
+ case *modelv2.TagValue_IntArray:
+ buf := bytes.NewBuffer(nil)
+ for _, i := range x.IntArray.GetValue() {
+ buf.Write(convert.Int64ToBytes(i))
+ }
+ return buf.Bytes(), nil
+ case *modelv2.TagValue_BinaryData:
+ return x.BinaryData, nil
+ }
+ return nil, ErrUnsupportedTagForIndexField
+}
+
+func (s *stream) buildEntity(value *streamv2.ElementValue) (tsdb.Entity, error) {
+ entity := make(tsdb.Entity, len(s.entityIndex))
+ for i, index := range s.entityIndex {
tag, err := getTagByOffset(value, index.family, index.tag)
if err != nil {
return nil, err
}
- entry, err := tagConvEntry(tag)
- if err != nil {
- return nil, err
+ e, errMarshal := marshalIndexFieldValue(tag)
+ if errMarshal != nil {
+ return nil, errMarshal
}
- entity = append(entity, entry)
+ entity[i] = e
}
return entity, nil
}
-func getTagByOffset(value *streamv2.ElementValue, fIndex, tIndex int) (*modelv2.Tag, error) {
+func getTagByOffset(value *streamv2.ElementValue, fIndex, tIndex int) (*modelv2.TagValue, error) {
if fIndex >= len(value.TagFamilies) {
return nil, errors.Wrap(ErrMalformedElement, "tag family offset is invalid")
}
@@ -160,17 +183,6 @@ func getTagByOffset(value *streamv2.ElementValue, fIndex, tIndex int) (*modelv2.
return family.GetTags()[tIndex], nil
}
-func tagConvEntry(tag *modelv2.Tag) (tsdb.Entry, error) {
- switch tag.GetValueType().(type) {
- case *modelv2.Tag_Str:
- return tsdb.Entry(tag.GetStr().GetValue()), nil
- case *modelv2.Tag_Int:
- return convert.Int64ToBytes(tag.GetInt().GetValue()), nil
- default:
- return nil, ErrUnsupportedTagTypeAsEntry
- }
-}
-
type writeCallback struct {
l *logger.Logger
schemaMap map[string]*stream
@@ -192,7 +204,7 @@ func (w *writeCallback) Rev(message bus.Message) (resp bus.Message) {
}
sm := writeEvent.WriteRequest.GetMetadata()
id := formatStreamID(sm.GetName(), sm.GetGroup())
- err := w.schemaMap[id].write(writeEvent.ShardID, writeEvent.WriteRequest.GetElement())
+ err := w.schemaMap[id].write(common.ShardID(writeEvent.ShardID), writeEvent.WriteRequest.GetElement())
if err != nil {
w.l.Debug().Err(err)
}
diff --git a/banyand/stream/stream_write_test.go b/banyand/stream/stream_write_test.go
index f02ff0a..1853a7f 100644
--- a/banyand/stream/stream_write_test.go
+++ b/banyand/stream/stream_write_test.go
@@ -26,6 +26,7 @@ import (
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/timestamppb"
+ "github.com/apache/skywalking-banyandb/api/common"
commonv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v2"
modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
streamv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/stream/v2"
@@ -196,7 +197,7 @@ func Test_Stream_Write(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
- err := s.write(tt.args.shardID, tt.args.ele)
+ err := s.write(common.ShardID(tt.args.shardID), tt.args.ele)
if tt.wantErr {
tester.Error(err)
return
@@ -237,7 +238,7 @@ func setup(t *assert.Assertions) (*stream, func()) {
}
func getEle(tags ...interface{}) *streamv2.ElementValue {
- searchableTags := make([]*modelv2.Tag, 0)
+ searchableTags := make([]*modelv2.TagValue, 0)
for _, tag := range tags {
searchableTags = append(searchableTags, getTag(tag))
}
@@ -247,9 +248,9 @@ func getEle(tags ...interface{}) *streamv2.ElementValue {
Timestamp: timestamppb.Now(),
TagFamilies: []*streamv2.ElementValue_TagFamily{
{
- Tags: []*modelv2.Tag{
+ Tags: []*modelv2.TagValue{
{
- ValueType: &modelv2.Tag_BinaryData{
+ Value: &modelv2.TagValue_BinaryData{
BinaryData: bb,
},
},
@@ -263,24 +264,24 @@ func getEle(tags ...interface{}) *streamv2.ElementValue {
return e
}
-func getTag(tag interface{}) *modelv2.Tag {
+func getTag(tag interface{}) *modelv2.TagValue {
if tag == nil {
- return &modelv2.Tag{
- ValueType: &modelv2.Tag_Null{},
+ return &modelv2.TagValue{
+ Value: &modelv2.TagValue_Null{},
}
}
switch t := tag.(type) {
case int:
- return &modelv2.Tag{
- ValueType: &modelv2.Tag_Int{
+ return &modelv2.TagValue{
+ Value: &modelv2.TagValue_Int{
Int: &modelv2.Int{
Value: int64(t),
},
},
}
case string:
- return &modelv2.Tag{
- ValueType: &modelv2.Tag_Str{
+ return &modelv2.TagValue{
+ Value: &modelv2.TagValue_Str{
Str: &modelv2.Str{
Value: t,
},
diff --git a/banyand/tsdb/block.go b/banyand/tsdb/block.go
index ad2483a..7d5168f 100644
--- a/banyand/tsdb/block.go
+++ b/banyand/tsdb/block.go
@@ -24,7 +24,12 @@ import (
"github.com/dgraph-io/ristretto/z"
+ "github.com/apache/skywalking-banyandb/api/common"
+ databasev2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
"github.com/apache/skywalking-banyandb/banyand/kv"
+ "github.com/apache/skywalking-banyandb/pkg/convert"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+ "github.com/apache/skywalking-banyandb/pkg/index/inverted"
"github.com/apache/skywalking-banyandb/pkg/logger"
)
@@ -33,13 +38,14 @@ type block struct {
l *logger.Logger
ref *z.Closer
- store kv.TimeSeriesStore
- treeIndex kv.Store
- closableLst []io.Closer
- endTime time.Time
- startTime time.Time
- segID uint16
- blockID uint16
+ store kv.TimeSeriesStore
+ primaryIndex kv.Store
+ invertedIndex inverted.GlobalStore
+ closableLst []io.Closer
+ endTime time.Time
+ startTime time.Time
+ segID uint16
+ blockID uint16
//revertedIndex kv.Store
}
@@ -70,10 +76,27 @@ func newBlock(ctx context.Context, opts blockOpts) (b *block, err error) {
kv.TSSWithLogger(b.l)); err != nil {
return nil, err
}
- if b.treeIndex, err = kv.OpenStore(0, b.path+"/t_index", kv.StoreWithLogger(b.l)); err != nil {
+ if b.primaryIndex, err = kv.OpenStore(0, b.path+"/p_index", kv.StoreWithLogger(b.l)); err != nil {
+ return nil, err
+ }
+ b.closableLst = append(b.closableLst, b.store, b.primaryIndex)
+ rules, ok := ctx.Value(indexRulesKey).([]*databasev2.IndexRule)
+ var specs []index.FieldSpec
+ for _, rule := range rules {
+ if rule.GetLocation() == databasev2.IndexRule_LOCATION_SERIES {
+ specs = append(specs, index.FieldSpec{
+ Name: rule.GetMetadata().GetName(),
+ })
+ }
+ }
+ if !ok || len(specs) == 0 {
+ return b, nil
+ }
+ b.invertedIndex = inverted.NewStore("inverted")
+ err = b.invertedIndex.Initialize(specs)
+ if err != nil {
return nil, err
}
- b.closableLst = append(b.closableLst, b.store, b.treeIndex)
return b, nil
}
@@ -104,9 +127,15 @@ type blockDelegate interface {
io.Closer
contains(ts time.Time) bool
write(key []byte, val []byte, ts time.Time) error
- writeLSMIndex(key []byte, val []byte) error
- writeInvertedIndex(key []byte, val []byte) error
+ writePrimaryIndex(field index.Field, id common.ItemID) error
+ writeLSMIndex(field index.Field, id common.ItemID) error
+ writeInvertedIndex(field index.Field, id common.ItemID) error
+ dataReader() kv.TimeSeriesReader
+ lsmIndexReader() index.Searcher
+ invertedIndexReader() index.Searcher
+ primaryIndexReader() index.Searcher
identity() (segID uint16, blockID uint16)
+ startTime() time.Time
}
var _ blockDelegate = (*bDelegate)(nil)
@@ -115,6 +144,26 @@ type bDelegate struct {
delegate *block
}
+func (d *bDelegate) dataReader() kv.TimeSeriesReader {
+ return d.delegate.store
+}
+
+func (d *bDelegate) lsmIndexReader() index.Searcher {
+ return d.delegate.invertedIndex.Searcher()
+}
+
+func (d *bDelegate) invertedIndexReader() index.Searcher {
+ return d.delegate.invertedIndex.Searcher()
+}
+
+func (d *bDelegate) primaryIndexReader() index.Searcher {
+ return d.delegate.primaryIndex
+}
+
+func (d *bDelegate) startTime() time.Time {
+ return d.delegate.startTime
+}
+
func (d *bDelegate) identity() (segID uint16, blockID uint16) {
return d.delegate.segID, d.delegate.blockID
}
@@ -123,12 +172,22 @@ func (d *bDelegate) write(key []byte, val []byte, ts time.Time) error {
return d.delegate.store.Put(key, val, uint64(ts.UnixNano()))
}
-func (d *bDelegate) writeLSMIndex(key []byte, val []byte) error {
- return d.delegate.treeIndex.Put(key, val)
+func (d *bDelegate) writePrimaryIndex(field index.Field, id common.ItemID) error {
+ return d.delegate.primaryIndex.Put(field.Marshal(), convert.Uint64ToBytes(uint64(id)))
}
-func (d *bDelegate) writeInvertedIndex(key []byte, val []byte) error {
- return d.delegate.treeIndex.Put(key, val)
+func (d *bDelegate) writeLSMIndex(field index.Field, id common.ItemID) error {
+ if d.delegate.invertedIndex == nil {
+ return nil
+ }
+ return d.delegate.invertedIndex.Insert(field, id)
+}
+
+func (d *bDelegate) writeInvertedIndex(field index.Field, id common.ItemID) error {
+ if d.delegate.invertedIndex == nil {
+ return nil
+ }
+ return d.delegate.invertedIndex.Insert(field, id)
}
func (d *bDelegate) contains(ts time.Time) bool {
diff --git a/banyand/tsdb/indexdb.go b/banyand/tsdb/indexdb.go
index 0b3fb80..c81c727 100644
--- a/banyand/tsdb/indexdb.go
+++ b/banyand/tsdb/indexdb.go
@@ -18,30 +18,34 @@
package tsdb
import (
- "bytes"
"context"
"time"
"github.com/pkg/errors"
"github.com/apache/skywalking-banyandb/api/common"
+ "github.com/apache/skywalking-banyandb/pkg/index"
)
type IndexDatabase interface {
- IndexWriterBuilder() IndexWriterBuilder
+ WriterBuilder() IndexWriterBuilder
+ Seek(field index.Field) ([]GlobalItemID, error)
}
type IndexWriter interface {
- WriteLSMIndex(name string, val []byte) error
- WriteInvertedIndex(name string, val []byte) error
+ WriteLSMIndex(field index.Field) error
+ WriteInvertedIndex(field index.Field) error
}
type IndexWriterBuilder interface {
Time(ts time.Time) IndexWriterBuilder
- GlobalItemID(itemID ItemID) IndexWriterBuilder
+ GlobalItemID(itemID GlobalItemID) IndexWriterBuilder
Build() (IndexWriter, error)
}
+type IndexSeekBuilder interface {
+}
+
var _ IndexDatabase = (*indexDB)(nil)
type indexDB struct {
@@ -49,7 +53,21 @@ type indexDB struct {
lst []*segment
}
-func (i *indexDB) IndexWriterBuilder() IndexWriterBuilder {
+func (i *indexDB) Seek(term index.Field) ([]GlobalItemID, error) {
+ var result []GlobalItemID
+ err := i.lst[0].globalIndex.GetAll(term.Marshal(), func(rawBytes []byte) error {
+ id := &GlobalItemID{}
+ err := id.UnMarshal(rawBytes)
+ if err != nil {
+ return err
+ }
+ result = append(result, *id)
+ return nil
+ })
+ return result, err
+}
+
+func (i *indexDB) WriterBuilder() IndexWriterBuilder {
return newIndexWriterBuilder(i.lst)
}
@@ -66,7 +84,7 @@ type indexWriterBuilder struct {
segments []*segment
ts time.Time
seg *segment
- globalItemID *ItemID
+ globalItemID *GlobalItemID
}
func (i *indexWriterBuilder) Time(ts time.Time) IndexWriterBuilder {
@@ -80,7 +98,7 @@ func (i *indexWriterBuilder) Time(ts time.Time) IndexWriterBuilder {
return i
}
-func (i *indexWriterBuilder) GlobalItemID(itemID ItemID) IndexWriterBuilder {
+func (i *indexWriterBuilder) GlobalItemID(itemID GlobalItemID) IndexWriterBuilder {
i.globalItemID = &itemID
return i
}
@@ -110,13 +128,13 @@ var _ IndexWriter = (*indexWriter)(nil)
type indexWriter struct {
seg *segment
ts time.Time
- itemID *ItemID
+ itemID *GlobalItemID
}
-func (i *indexWriter) WriteLSMIndex(name string, val []byte) error {
- return i.seg.globalIndex.Put(bytes.Join([][]byte{[]byte(name), val}, nil), i.itemID.Marshal())
+func (i *indexWriter) WriteLSMIndex(field index.Field) error {
+ return i.seg.globalIndex.PutWithVersion(field.Marshal(), i.itemID.Marshal(), uint64(i.ts.UnixNano()))
}
-func (i *indexWriter) WriteInvertedIndex(name string, val []byte) error {
- return i.seg.globalIndex.Put(bytes.Join([][]byte{[]byte(name), val}, nil), i.itemID.Marshal())
+func (i *indexWriter) WriteInvertedIndex(field index.Field) error {
+ return i.seg.globalIndex.PutWithVersion(field.Marshal(), i.itemID.Marshal(), uint64(i.ts.UnixNano()))
}
diff --git a/banyand/tsdb/series.go b/banyand/tsdb/series.go
index bdbb7d4..efdf8ba 100644
--- a/banyand/tsdb/series.go
+++ b/banyand/tsdb/series.go
@@ -26,7 +26,6 @@ import (
"go.uber.org/multierr"
"github.com/apache/skywalking-banyandb/api/common"
- modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
"github.com/apache/skywalking-banyandb/pkg/convert"
)
@@ -35,42 +34,26 @@ var (
ErrItemIDMalformed = errors.New("serialized item id is malformed")
)
-type Iterator interface {
- Next() bool
- Val() Item
- Close() error
-}
-
-type Item interface {
- Val(family string) []byte
- SortingVal() []byte
-}
-
-type ConditionValue struct {
- Values [][]byte
- Op modelv2.PairQuery_BinaryOp
-}
-
-type Condition map[string][]ConditionValue
-
-type ItemID struct {
- shardID common.ShardID
- segID uint16
- blockID uint16
- id []byte
+type GlobalItemID struct {
+ shardID common.ShardID
+ segID uint16
+ blockID uint16
+ seriesID common.SeriesID
+ id common.ItemID
}
-func (i *ItemID) Marshal() []byte {
+func (i *GlobalItemID) Marshal() []byte {
return bytes.Join([][]byte{
convert.Uint32ToBytes(uint32(i.shardID)),
convert.Uint16ToBytes(i.segID),
convert.Uint16ToBytes(i.blockID),
- i.id,
+ convert.Uint64ToBytes(uint64(i.seriesID)),
+ convert.Uint64ToBytes(uint64(i.id)),
}, nil)
}
-func (i *ItemID) UnMarshal(data []byte) error {
- if len(data) <= 32+16+16 {
+func (i *GlobalItemID) UnMarshal(data []byte) error {
+ if len(data) <= 32+16+16+64+64 {
return ErrItemIDMalformed
}
var offset int
@@ -80,52 +63,46 @@ func (i *ItemID) UnMarshal(data []byte) error {
offset += 2
i.blockID = convert.BytesToUint16(data[offset : offset+2])
offset += 2
- i.id = data[offset:]
+ i.seriesID = common.SeriesID(convert.BytesToUint64(data[offset : offset+8]))
+ offset += 8
+ i.id = common.ItemID(convert.BytesToUint64(data[offset:]))
return nil
}
type TimeRange struct {
Start time.Time
Duration time.Duration
+ End time.Time
+}
+
+func (t TimeRange) contains(unixNano uint64) bool {
+ tp := time.Unix(0, int64(unixNano))
+ if tp.Equal(t.End) || tp.After(t.End) {
+ return false
+ }
+ return tp.Equal(t.Start) || tp.After(t.Start)
+}
+
+func NewTimeRange(Start time.Time, Duration time.Duration) TimeRange {
+ return TimeRange{
+ Start: Start,
+ Duration: Duration,
+ End: Start.Add(Duration),
+ }
}
type Series interface {
ID() common.SeriesID
Span(timeRange TimeRange) (SeriesSpan, error)
- Get(id ItemID) (Item, error)
+ Get(id GlobalItemID) (Item, error)
}
type SeriesSpan interface {
io.Closer
WriterBuilder() WriterBuilder
- Iterator() Iterator
SeekerBuilder() SeekerBuilder
}
-type WriterBuilder interface {
- Family(name string, val []byte) WriterBuilder
- Time(ts time.Time) WriterBuilder
- Val(val []byte) WriterBuilder
- Build() (Writer, error)
-}
-
-type Writer interface {
- IndexWriter
- Write() (ItemID, error)
- ItemID() ItemID
-}
-
-type SeekerBuilder interface {
- Filter(condition Condition) SeekerBuilder
- OrderByIndex(name string, order modelv2.QueryOrder_Sort) SeekerBuilder
- OrderByTime(order modelv2.QueryOrder_Sort) SeekerBuilder
- Build() Seeker
-}
-
-type Seeker interface {
- Seek() Iterator
-}
-
var _ Series = (*series)(nil)
type series struct {
@@ -134,6 +111,10 @@ type series struct {
shardID common.ShardID
}
+func (s *series) Get(id GlobalItemID) (Item, error) {
+ panic("implement me")
+}
+
func newSeries(id common.SeriesID, blockDB blockDatabase) *series {
return &series{
id: id,
@@ -151,19 +132,16 @@ func (s *series) Span(timeRange TimeRange) (SeriesSpan, error) {
if len(blocks) < 1 {
return nil, ErrEmptySeriesSpan
}
- return newSeriesSpan(blocks, s.id, s.shardID), nil
-}
-
-func (s *series) Get(id ItemID) (Item, error) {
- panic("not implemented")
+ return newSeriesSpan(timeRange, blocks, s.id, s.shardID), nil
}
var _ SeriesSpan = (*seriesSpan)(nil)
type seriesSpan struct {
- blocks []blockDelegate
- seriesID common.SeriesID
- shardID common.ShardID
+ blocks []blockDelegate
+ seriesID common.SeriesID
+ shardID common.ShardID
+ timeRange TimeRange
}
func (s *seriesSpan) Close() (err error) {
@@ -177,123 +155,16 @@ func (s *seriesSpan) WriterBuilder() WriterBuilder {
return newWriterBuilder(s)
}
-func (s *seriesSpan) Iterator() Iterator {
- panic("implement me")
-}
-
func (s *seriesSpan) SeekerBuilder() SeekerBuilder {
- panic("implement me")
+ return newSeekerBuilder(s)
}
-func newSeriesSpan(blocks []blockDelegate, id common.SeriesID, shardID common.ShardID) *seriesSpan {
+func newSeriesSpan(timeRange TimeRange, blocks []blockDelegate,
+ id common.SeriesID, shardID common.ShardID) *seriesSpan {
return &seriesSpan{
- blocks: blocks,
- seriesID: id,
- shardID: shardID,
- }
-}
-
-var _ WriterBuilder = (*writerBuilder)(nil)
-
-type writerBuilder struct {
- series *seriesSpan
- block blockDelegate
- values []struct {
- family []byte
- val []byte
- }
- ts time.Time
- seriesIDBytes []byte
-}
-
-func (w *writerBuilder) Family(name string, val []byte) WriterBuilder {
- w.values = append(w.values, struct {
- family []byte
- val []byte
- }{family: bytes.Join([][]byte{w.seriesIDBytes, hash([]byte(name))}, nil), val: val})
- return w
-}
-
-func (w *writerBuilder) Time(ts time.Time) WriterBuilder {
- w.ts = ts
- for _, b := range w.series.blocks {
- if b.contains(ts) {
- w.block = b
- break
- }
- }
- return w
-}
-
-func (w *writerBuilder) Val(val []byte) WriterBuilder {
- w.values = append(w.values, struct {
- family []byte
- val []byte
- }{val: val})
- return w
-}
-
-var ErrNoTime = errors.New("no time specified")
-var ErrNoVal = errors.New("no value specified")
-
-func (w *writerBuilder) Build() (Writer, error) {
- if w.block == nil {
- return nil, errors.WithStack(ErrNoTime)
- }
- if len(w.values) < 1 {
- return nil, errors.WithStack(ErrNoVal)
- }
- segID, blockID := w.block.identity()
- return &writer{
- block: w.block,
- ts: w.ts,
- itemID: &ItemID{
- shardID: w.series.shardID,
- segID: segID,
- blockID: blockID,
- id: bytes.Join([][]byte{w.seriesIDBytes, convert.Int64ToBytes(w.ts.UnixNano())}, nil),
- },
- columns: w.values,
- }, nil
-}
-
-func newWriterBuilder(seriesSpan *seriesSpan) WriterBuilder {
- return &writerBuilder{
- series: seriesSpan,
- seriesIDBytes: convert.Uint64ToBytes(uint64(seriesSpan.seriesID)),
- }
-}
-
-var _ Writer = (*writer)(nil)
-
-type writer struct {
- block blockDelegate
- ts time.Time
- columns []struct {
- family []byte
- val []byte
- }
- itemID *ItemID
-}
-
-func (w *writer) ItemID() ItemID {
- return *w.itemID
-}
-
-func (w *writer) WriteLSMIndex(name string, val []byte) error {
- return w.block.writeLSMIndex(bytes.Join([][]byte{[]byte(name), val}, nil), w.itemID.id)
-}
-
-func (w *writer) WriteInvertedIndex(name string, val []byte) error {
- return w.block.writeInvertedIndex(bytes.Join([][]byte{[]byte(name), val}, nil), w.itemID.id)
-}
-
-func (w *writer) Write() (id ItemID, err error) {
- for _, c := range w.columns {
- err = w.block.write(c.family, c.val, w.ts)
- if err != nil {
- return id, err
- }
+ blocks: blocks,
+ seriesID: id,
+ shardID: shardID,
+ timeRange: timeRange,
}
- return id, nil
}
diff --git a/banyand/tsdb/series_seek.go b/banyand/tsdb/series_seek.go
new file mode 100644
index 0000000..478efa0
--- /dev/null
+++ b/banyand/tsdb/series_seek.go
@@ -0,0 +1,128 @@
+// 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 tsdb
+
+import (
+ "github.com/apache/skywalking-banyandb/api/common"
+ databasev2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
+ modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
+ "github.com/apache/skywalking-banyandb/banyand/kv"
+)
+
+type Iterator interface {
+ Next() bool
+ Val() Item
+ Close() error
+}
+
+type Item interface {
+ Val(family string) ([]byte, error)
+ ID() common.ItemID
+ SortedField() []byte
+ Time() uint64
+}
+
+type SeekerBuilder interface {
+ Filter(indexRule *databasev2.IndexRule, condition Condition) SeekerBuilder
+ OrderByIndex(indexRule *databasev2.IndexRule, order modelv2.QueryOrder_Sort) SeekerBuilder
+ OrderByTime(order modelv2.QueryOrder_Sort) SeekerBuilder
+ Build() (Seeker, error)
+}
+
+type Seeker interface {
+ Seek() ([]Iterator, error)
+}
+
+var _ SeekerBuilder = (*seekerBuilder)(nil)
+
+type seekerBuilder struct {
+ seriesSpan *seriesSpan
+
+ conditions []struct {
+ indexRuleType databasev2.IndexRule_Type
+ indexRule string
+ condition Condition
+ }
+ order modelv2.QueryOrder_Sort
+ indexRuleForSorting *databasev2.IndexRule
+}
+
+func (s *seekerBuilder) Build() (Seeker, error) {
+ indexFilter, err := s.buildIndexFilter()
+ if err != nil {
+ return nil, err
+ }
+ filters := []filterFn{
+ indexFilter,
+ func(item Item) bool {
+ return s.seriesSpan.timeRange.contains(item.Time())
+ },
+ }
+ return newSeeker(s.buildSeries(filters)), nil
+}
+
+func newSeekerBuilder(s *seriesSpan) SeekerBuilder {
+ return &seekerBuilder{
+ seriesSpan: s,
+ }
+}
+
+var _ Seeker = (*seeker)(nil)
+
+type seeker struct {
+ series []Iterator
+}
+
+func (s *seeker) Seek() ([]Iterator, error) {
+ return s.series, nil
+}
+
+func newSeeker(series []Iterator) Seeker {
+ return &seeker{
+ series: series,
+ }
+}
+
+var _ Item = (*item)(nil)
+
+type item struct {
+ itemID common.ItemID
+ data kv.TimeSeriesReader
+ seriesID common.SeriesID
+ sortedField []byte
+}
+
+func (i *item) Time() uint64 {
+ return uint64(i.itemID)
+}
+
+func (i *item) SortedField() []byte {
+ return i.sortedField
+}
+
+func (i *item) Val(family string) ([]byte, error) {
+ d := dataBucket{
+ seriesID: i.seriesID,
+ family: []byte(family),
+ }
+ return i.data.Get(d.marshal(), uint64(i.itemID))
+}
+
+func (i *item) ID() common.ItemID {
+ return i.itemID
+}
diff --git a/banyand/tsdb/series_seek_filter.go b/banyand/tsdb/series_seek_filter.go
new file mode 100644
index 0000000..65147ea
--- /dev/null
+++ b/banyand/tsdb/series_seek_filter.go
@@ -0,0 +1,104 @@
+// 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 tsdb
+
+import (
+ "github.com/pkg/errors"
+
+ databasev2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting/roaring"
+)
+
+var ErrUnsupportedIndexRule = errors.New("the index rule is not supported")
+
+type Condition map[string][]index.ConditionValue
+
+func (s *seekerBuilder) Filter(indexRule *databasev2.IndexRule, condition Condition) SeekerBuilder {
+ s.conditions = append(s.conditions, struct {
+ indexRuleType databasev2.IndexRule_Type
+ indexRule string
+ condition Condition
+ }{
+ indexRuleType: indexRule.GetType(),
+ indexRule: indexRule.GetMetadata().GetName(),
+ condition: condition,
+ })
+ return s
+}
+
+func (s *seekerBuilder) buildIndexFilter() (filterFn, error) {
+ var treeIndexCondition, invertedIndexCondition []index.Condition
+ for _, condition := range s.conditions {
+ if len(condition.condition) > 1 {
+ //TODO:// should support composite index rule
+ return nil, ErrUnsupportedIndexRule
+ }
+ var cond index.Condition
+ term := index.Term{
+ SeriesID: s.seriesSpan.seriesID,
+ IndexRule: condition.indexRule,
+ }
+ for _, c := range condition.condition {
+ cond[term] = c
+ break
+ }
+ switch condition.indexRuleType {
+ case databasev2.IndexRule_TYPE_TREE:
+ treeIndexCondition = append(treeIndexCondition, cond)
+ case databasev2.IndexRule_TYPE_INVERTED:
+ invertedIndexCondition = append(invertedIndexCondition, cond)
+ }
+ }
+ allItemIDs := roaring.NewPostingList()
+ addIDs := func(allList posting.List, searcher index.Searcher, cond index.Condition) error {
+ tree, err := index.BuildTree(searcher, cond)
+ if err != nil {
+ return err
+ }
+ list, err := tree.Execute()
+ if err != nil {
+ return err
+ }
+ err = allList.Union(list)
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ for _, b := range s.seriesSpan.blocks {
+ for _, tCond := range treeIndexCondition {
+ err := addIDs(allItemIDs, b.lsmIndexReader(), tCond)
+ if err != nil {
+ return nil, err
+ }
+ }
+ for _, iCond := range invertedIndexCondition {
+ err := addIDs(allItemIDs, b.invertedIndexReader(), iCond)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return func(item Item) bool {
+ return allItemIDs.Contains(item.ID())
+ }, nil
+}
+
+type filterFn func(item Item) bool
diff --git a/banyand/tsdb/series_seek_sort.go b/banyand/tsdb/series_seek_sort.go
new file mode 100644
index 0000000..1646bce
--- /dev/null
+++ b/banyand/tsdb/series_seek_sort.go
@@ -0,0 +1,200 @@
+// 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 tsdb
+
+import (
+ "sort"
+
+ "github.com/apache/skywalking-banyandb/api/common"
+ databasev2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
+ modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
+ "github.com/apache/skywalking-banyandb/banyand/kv"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+)
+
+func (s *seekerBuilder) OrderByIndex(indexRule *databasev2.IndexRule, order modelv2.QueryOrder_Sort) SeekerBuilder {
+ s.indexRuleForSorting = indexRule
+ s.order = order
+ return s
+}
+
+func (s *seekerBuilder) OrderByTime(order modelv2.QueryOrder_Sort) SeekerBuilder {
+ s.order = order
+ s.indexRuleForSorting = nil
+ return s
+}
+
+func (s *seekerBuilder) buildSeries(filters []filterFn) []Iterator {
+ if s.indexRuleForSorting == nil {
+ return s.buildSeriesByIndex(filters)
+ }
+ return s.buildSeriesByTime(filters)
+}
+
+func (s *seekerBuilder) buildSeriesByIndex(filters []filterFn) (series []Iterator) {
+ for _, b := range s.seriesSpan.blocks {
+ switch s.indexRuleForSorting.GetType() {
+ case databasev2.IndexRule_TYPE_TREE:
+ series = append(series, newSearcherIterator(
+ b.lsmIndexReader().
+ FieldIterator([]byte(s.indexRuleForSorting.GetMetadata().GetName()), s.order),
+ b.dataReader(),
+ s.seriesSpan.seriesID,
+ filters,
+ ))
+ case databasev2.IndexRule_TYPE_INVERTED:
+ series = append(series, newSearcherIterator(b.invertedIndexReader().
+ FieldIterator([]byte(s.indexRuleForSorting.GetMetadata().GetName()), s.order),
+ b.dataReader(),
+ s.seriesSpan.seriesID,
+ filters,
+ ))
+ }
+ }
+ return
+}
+
+func (s *seekerBuilder) buildSeriesByTime(filters []filterFn) []Iterator {
+ bb := s.seriesSpan.blocks
+ switch s.order {
+ case modelv2.QueryOrder_SORT_ASC:
+ sort.SliceStable(bb, func(i, j int) bool {
+ return bb[i].startTime().Before(bb[j].startTime())
+ })
+
+ case modelv2.QueryOrder_SORT_DESC:
+ sort.SliceStable(bb, func(i, j int) bool {
+ return bb[i].startTime().After(bb[j].startTime())
+ })
+ }
+ delegated := make([]Iterator, len(bb))
+ for _, b := range bb {
+ delegated = append(delegated, newSearcherIterator(b.
+ primaryIndexReader().
+ FieldIterator(
+ s.seriesSpan.seriesID.Marshal(),
+ s.order,
+ ), b.dataReader(), s.seriesSpan.seriesID, filters))
+ }
+ return []Iterator{newMergedIterator(delegated)}
+}
+
+var _ Iterator = (*searcherIterator)(nil)
+
+type searcherIterator struct {
+ fieldIterator index.FieldIterator
+ curKey []byte
+ cur posting.Iterator
+ data kv.TimeSeriesReader
+ seriesID common.SeriesID
+ filters []filterFn
+}
+
+func (s *searcherIterator) Next() bool {
+ if s.cur == nil {
+ if s.fieldIterator.Next() {
+ v := s.fieldIterator.Val()
+ s.cur = v.Value.Iterator()
+ s.curKey = v.Key
+ } else {
+ _ = s.Close()
+ return false
+ }
+ }
+ if s.cur.Next() {
+ for _, filter := range s.filters {
+ if !filter(s.Val()) {
+ return s.Next()
+ }
+ }
+ return true
+ }
+ _ = s.cur.Close()
+ s.cur = nil
+ return s.Next()
+}
+
+func (s *searcherIterator) Val() Item {
+ return &item{
+ sortedField: s.curKey,
+ itemID: s.cur.Current(),
+ data: s.data,
+ seriesID: s.seriesID,
+ }
+}
+
+func (s *searcherIterator) Close() error {
+ return s.fieldIterator.Close()
+}
+
+func newSearcherIterator(fieldIterator index.FieldIterator, data kv.TimeSeriesReader, seriesID common.SeriesID, filters []filterFn) Iterator {
+ return &searcherIterator{
+ fieldIterator: fieldIterator,
+ data: data,
+ seriesID: seriesID,
+ filters: filters,
+ }
+}
+
+var _ Iterator = (*mergedIterator)(nil)
+
+type mergedIterator struct {
+ curr Iterator
+ index int
+ delegated []Iterator
+ closed bool
+}
+
+func (m *mergedIterator) Next() bool {
+ if m.closed {
+ return false
+ }
+ if m.curr == nil {
+ m.index++
+ if m.index >= len(m.delegated) {
+ _ = m.Close()
+ return false
+ } else {
+ m.curr = m.delegated[m.index]
+ }
+ }
+ hasNext := m.curr.Next()
+ if !hasNext {
+ _ = m.curr.Close()
+ m.curr = nil
+ return m.Next()
+ }
+ return true
+}
+
+func (m *mergedIterator) Val() Item {
+ return m.curr.Val()
+}
+
+func (m *mergedIterator) Close() error {
+ m.closed = true
+ return nil
+}
+
+func newMergedIterator(delegated []Iterator) Iterator {
+ return &mergedIterator{
+ index: -1,
+ delegated: delegated,
+ }
+}
diff --git a/banyand/tsdb/series_write.go b/banyand/tsdb/series_write.go
new file mode 100644
index 0000000..0f69332
--- /dev/null
+++ b/banyand/tsdb/series_write.go
@@ -0,0 +1,177 @@
+// 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 tsdb
+
+import (
+ "bytes"
+ "time"
+
+ "github.com/pkg/errors"
+
+ "github.com/apache/skywalking-banyandb/api/common"
+ "github.com/apache/skywalking-banyandb/pkg/convert"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+)
+
+type WriterBuilder interface {
+ Family(name string, val []byte) WriterBuilder
+ Time(ts time.Time) WriterBuilder
+ Val(val []byte) WriterBuilder
+ Build() (Writer, error)
+}
+
+type Writer interface {
+ IndexWriter
+ Write() (GlobalItemID, error)
+ ItemID() GlobalItemID
+}
+
+var _ WriterBuilder = (*writerBuilder)(nil)
+
+type writerBuilder struct {
+ series *seriesSpan
+ block blockDelegate
+ values []struct {
+ family []byte
+ val []byte
+ }
+ ts time.Time
+ seriesIDBytes []byte
+}
+
+func (w *writerBuilder) Family(name string, val []byte) WriterBuilder {
+ w.values = append(w.values, struct {
+ family []byte
+ val []byte
+ }{family: []byte(name), val: val})
+ return w
+}
+
+func (w *writerBuilder) Time(ts time.Time) WriterBuilder {
+ w.ts = ts
+ for _, b := range w.series.blocks {
+ if b.contains(ts) {
+ w.block = b
+ break
+ }
+ }
+ return w
+}
+
+func (w *writerBuilder) Val(val []byte) WriterBuilder {
+ w.values = append(w.values, struct {
+ family []byte
+ val []byte
+ }{val: val})
+ return w
+}
+
+var ErrNoTime = errors.New("no time specified")
+var ErrNoVal = errors.New("no value specified")
+
+func (w *writerBuilder) Build() (Writer, error) {
+ if w.block == nil {
+ return nil, errors.WithStack(ErrNoTime)
+ }
+ if len(w.values) < 1 {
+ return nil, errors.WithStack(ErrNoVal)
+ }
+ segID, blockID := w.block.identity()
+ return &writer{
+ block: w.block,
+ ts: w.ts,
+ itemID: &GlobalItemID{
+ shardID: w.series.shardID,
+ segID: segID,
+ blockID: blockID,
+ seriesID: w.series.seriesID,
+ id: common.ItemID(uint64(w.ts.UnixNano())),
+ },
+ columns: w.values,
+ }, nil
+}
+
+func newWriterBuilder(seriesSpan *seriesSpan) WriterBuilder {
+ return &writerBuilder{
+ series: seriesSpan,
+ seriesIDBytes: seriesSpan.seriesID.Marshal(),
+ }
+}
+
+var _ Writer = (*writer)(nil)
+
+type writer struct {
+ block blockDelegate
+ ts time.Time
+ columns []struct {
+ family []byte
+ val []byte
+ }
+ itemID *GlobalItemID
+}
+
+func (w *writer) ItemID() GlobalItemID {
+ return *w.itemID
+}
+
+func (w *writer) WriteLSMIndex(field index.Field) error {
+ t := index.Term{
+ SeriesID: w.itemID.seriesID,
+ IndexRule: string(field.Term),
+ }
+ field.Term = t.Marshal()
+ return w.block.writeLSMIndex(field, w.itemID.id)
+}
+
+func (w *writer) WriteInvertedIndex(field index.Field) error {
+ t := index.Term{
+ SeriesID: w.itemID.seriesID,
+ IndexRule: string(field.Term),
+ }
+ field.Term = t.Marshal()
+ return w.block.writeInvertedIndex(field, w.itemID.id)
+}
+
+type dataBucket struct {
+ seriesID common.SeriesID
+ family []byte
+}
+
+func (d dataBucket) marshal() []byte {
+ return bytes.Join([][]byte{
+ d.seriesID.Marshal(),
+ hash(d.family),
+ }, nil)
+}
+
+func (w *writer) Write() (id GlobalItemID, err error) {
+ for _, c := range w.columns {
+ err = w.block.write(dataBucket{
+ seriesID: w.itemID.seriesID,
+ family: c.family,
+ }.marshal(),
+ c.val, w.ts)
+ if err != nil {
+ return id, err
+ }
+ }
+ return id, w.block.writePrimaryIndex(index.Field{
+ Term: id.seriesID.Marshal(),
+ Value: convert.Int64ToBytes(w.ts.UnixNano()),
+ }, id.id)
+}
diff --git a/banyand/tsdb/seriesdb.go b/banyand/tsdb/seriesdb.go
index 8c0e9fb..24a622f 100644
--- a/banyand/tsdb/seriesdb.go
+++ b/banyand/tsdb/seriesdb.go
@@ -183,7 +183,7 @@ func newSeriesDataBase(ctx context.Context, shardID common.ShardID, path string,
return nil, logger.ErrNoLoggerInContext
}
if pl, ok := parentLogger.(*logger.Logger); ok {
- sdb.l = pl.Named("series")
+ sdb.l = pl.Named("seriesSpan")
}
var err error
sdb.seriesMetadata, err = kv.OpenStore(0, path+"/md", kv.StoreWithNamedLogger("metadata", sdb.l))
diff --git a/banyand/tsdb/tsdb.go b/banyand/tsdb/tsdb.go
index 66ba915..0d3da45 100644
--- a/banyand/tsdb/tsdb.go
+++ b/banyand/tsdb/tsdb.go
@@ -30,12 +30,13 @@ import (
"go.uber.org/multierr"
"github.com/apache/skywalking-banyandb/api/common"
+ databasev2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v2"
"github.com/apache/skywalking-banyandb/pkg/logger"
)
const (
shardTemplate = "%s/shard-%d"
- seriesTemplate = "%s/series"
+ seriesTemplate = "%s/seriesSpan"
segTemplate = "%s/seg-%s"
blockTemplate = "%s/block-%s"
globalIndexTemplate = "%s/index"
@@ -47,11 +48,14 @@ const (
)
var ErrInvalidShardID = errors.New("invalid shard id")
+var indexRulesKey = contextIndexRulesKey{}
+
+type contextIndexRulesKey struct{}
type Database interface {
io.Closer
Shards() []Shard
- Shard(id uint) (Shard, error)
+ Shard(id common.ShardID) (Shard, error)
}
type Shard interface {
@@ -63,8 +67,9 @@ type Shard interface {
var _ Database = (*database)(nil)
type DatabaseOpts struct {
- Location string
- ShardNum uint32
+ Location string
+ ShardNum uint32
+ IndexRules []*databasev2.IndexRule
}
type database struct {
@@ -80,8 +85,8 @@ func (d *database) Shards() []Shard {
return d.sLst
}
-func (d *database) Shard(id uint) (Shard, error) {
- if id >= uint(len(d.sLst)) {
+func (d *database) Shard(id common.ShardID) (Shard, error) {
+ if uint(id) >= uint(len(d.sLst)) {
return nil, ErrInvalidShardID
}
return d.sLst[id], nil
@@ -115,6 +120,7 @@ func OpenDatabase(ctx context.Context, opts DatabaseOpts) (Database, error) {
return nil, errors.Wrap(err, "failed to read directory contents failed")
}
thisContext := context.WithValue(ctx, logger.ContextKey, db.logger)
+ thisContext = context.WithValue(thisContext, indexRulesKey, opts.IndexRules)
if len(entries) > 0 {
return loadDatabase(thisContext, db)
}
diff --git a/pkg/index/index.go b/pkg/index/index.go
new file mode 100644
index 0000000..46c70be
--- /dev/null
+++ b/pkg/index/index.go
@@ -0,0 +1,63 @@
+// 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 index
+
+import (
+ "bytes"
+
+ modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+)
+
+type Field struct {
+ Term []byte
+ Value []byte
+}
+
+func (f Field) Marshal() []byte {
+ return bytes.Join([][]byte{f.Term, f.Value}, nil)
+}
+
+type FieldSpec struct {
+ Name string
+}
+
+type RangeOpts struct {
+ Upper []byte
+ Lower []byte
+ IncludesUpper bool
+ IncludesLower bool
+}
+
+type FieldIterator interface {
+ Next() bool
+ Val() *PostingValue
+ Close() error
+}
+
+type PostingValue struct {
+ Key []byte
+ Value posting.List
+}
+
+type Searcher interface {
+ MatchField(fieldName []byte) (list posting.List)
+ MatchTerms(field Field) (list posting.List)
+ Range(fieldName []byte, opts RangeOpts) (list posting.List)
+ FieldIterator(fieldName []byte, order modelv2.QueryOrder_Sort) FieldIterator
+}
diff --git a/banyand/index/tsdb/field_map.go b/pkg/index/inverted/field_map.go
similarity index 87%
copy from banyand/index/tsdb/field_map.go
copy to pkg/index/inverted/field_map.go
index 4d89713..f8d3789 100644
--- a/banyand/index/tsdb/field_map.go
+++ b/pkg/index/inverted/field_map.go
@@ -15,13 +15,14 @@
// specific language governing permissions and limitations
// under the License.
-package tsdb
+package inverted
import (
"github.com/pkg/errors"
"github.com/apache/skywalking-banyandb/api/common"
"github.com/apache/skywalking-banyandb/pkg/convert"
+ "github.com/apache/skywalking-banyandb/pkg/index"
)
var ErrFieldAbsent = errors.New("field doesn't exist")
@@ -50,10 +51,10 @@ func (fm *fieldMap) get(key []byte) (*fieldValue, bool) {
return v, ok
}
-func (fm *fieldMap) put(fv *Field, id common.ChunkID) error {
- pm, ok := fm.get(fv.Name)
+func (fm *fieldMap) put(fv index.Field, id common.ItemID) error {
+ pm, ok := fm.get(fv.Term)
if !ok {
- return errors.Wrapf(ErrFieldAbsent, "filed Name:%s", fv.Name)
+ return errors.Wrapf(ErrFieldAbsent, "filed Term:%s", fv.Term)
}
return pm.value.put(fv.Value, id)
}
diff --git a/api/proto/banyandb/model/v2/write.proto b/pkg/index/inverted/inverted.go
similarity index 53%
rename from api/proto/banyandb/model/v2/write.proto
rename to pkg/index/inverted/inverted.go
index 4636bd3..d610d54 100644
--- a/api/proto/banyandb/model/v2/write.proto
+++ b/pkg/index/inverted/inverted.go
@@ -15,23 +15,38 @@
// specific language governing permissions and limitations
// under the License.
-syntax = "proto3";
+package inverted
-option java_package = "org.apache.skywalking.banyandb.model.v2";
-option go_package = "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2";
+import (
+ "github.com/apache/skywalking-banyandb/api/common"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+)
-package banyandb.model.v2;
+type GlobalStore interface {
+ Searcher() index.Searcher
+ Initialize(fields []index.FieldSpec) error
+ Insert(field index.Field, docID common.ItemID) error
+}
+
+type store struct {
+ memTable *MemTable
+ //TODO: add data tables
+}
+
+func (s *store) Searcher() index.Searcher {
+ return s.memTable
+}
+
+func (s *store) Initialize(fields []index.FieldSpec) error {
+ return s.memTable.Initialize(fields)
+}
-import "google/protobuf/struct.proto";
-import "banyandb/model/v2/common.proto";
+func (s *store) Insert(field index.Field, chunkID common.ItemID) error {
+ return s.memTable.Insert(field, chunkID)
+}
-message Tag {
- oneof value_type {
- google.protobuf.NullValue null = 1;
- Str str = 2;
- StrArray str_array = 3;
- Int int = 4;
- IntArray int_array = 5;
- bytes binary_data = 6;
- }
+func NewStore(name string) GlobalStore {
+ return &store{
+ memTable: NewMemTable(name),
+ }
}
diff --git a/pkg/index/inverted/mem.go b/pkg/index/inverted/mem.go
new file mode 100644
index 0000000..e2db1f6
--- /dev/null
+++ b/pkg/index/inverted/mem.go
@@ -0,0 +1,155 @@
+// 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 inverted
+
+import (
+ "bytes"
+ "sort"
+
+ "github.com/pkg/errors"
+
+ "github.com/apache/skywalking-banyandb/api/common"
+ modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting/roaring"
+)
+
+var ErrFieldsAbsent = errors.New("fields are absent")
+
+var _ index.Searcher = (*MemTable)(nil)
+
+type MemTable struct {
+ terms *fieldMap
+ name string
+}
+
+func NewMemTable(name string) *MemTable {
+ return &MemTable{
+ name: name,
+ }
+}
+
+func (m *MemTable) Initialize(fields []index.FieldSpec) error {
+ if len(fields) < 1 {
+ return ErrFieldsAbsent
+ }
+ m.terms = newFieldMap(len(fields))
+ for _, f := range fields {
+ m.terms.createKey([]byte(f.Name))
+ }
+ return nil
+}
+
+func (m *MemTable) Insert(field index.Field, chunkID common.ItemID) error {
+ return m.terms.put(field, chunkID)
+}
+
+func (m *MemTable) MatchField(fieldName []byte) (list posting.List) {
+ fieldsValues, ok := m.terms.get(fieldName)
+ if !ok {
+ return roaring.EmptyPostingList
+ }
+ return fieldsValues.value.allValues()
+}
+
+var _ index.FieldIterator = (*fIterator)(nil)
+
+type fIterator struct {
+ index int
+ val *index.PostingValue
+ keys [][]byte
+ valueRepo *postingMap
+ closed bool
+}
+
+func (f *fIterator) Next() bool {
+ if f.closed {
+ return false
+ }
+ f.index++
+ if f.index >= len(f.keys) {
+ _ = f.Close()
+ return false
+ }
+ f.val = f.valueRepo.getEntry(f.keys[f.index])
+ if f.val == nil {
+ return f.Next()
+ }
+ return true
+}
+
+func (f *fIterator) Val() *index.PostingValue {
+ return f.val
+}
+
+func (f *fIterator) Close() error {
+ f.closed = true
+ return nil
+}
+
+func newFieldIterator(keys [][]byte, fValue *postingMap) index.FieldIterator {
+ return &fIterator{
+ keys: keys,
+ valueRepo: fValue,
+ index: -1,
+ }
+}
+
+func (m *MemTable) FieldIterator(fieldName []byte, order modelv2.QueryOrder_Sort) index.FieldIterator {
+ fieldsValues, ok := m.terms.get(fieldName)
+ if !ok {
+ return nil
+ }
+ fValue := fieldsValues.value
+ var keys [][]byte
+ {
+ fValue.mutex.RLock()
+ defer fValue.mutex.RUnlock()
+ for _, value := range fValue.repo {
+ keys = append(keys, value.Key)
+ }
+ }
+ switch order {
+ case modelv2.QueryOrder_SORT_ASC:
+ sort.SliceStable(keys, func(i, j int) bool {
+ return bytes.Compare(keys[i], keys[j]) < 0
+ })
+ case modelv2.QueryOrder_SORT_DESC:
+ sort.SliceStable(keys, func(i, j int) bool {
+ return bytes.Compare(keys[i], keys[j]) > 0
+ })
+ }
+ return newFieldIterator(keys, fValue)
+}
+
+func (m *MemTable) MatchTerms(field index.Field) (list posting.List) {
+ fieldsValues, ok := m.terms.get(field.Term)
+ if !ok {
+ return roaring.EmptyPostingList
+ }
+ return fieldsValues.value.get(field.Value).Clone()
+}
+
+func (m *MemTable) Range(fieldName []byte, opts index.RangeOpts) (list posting.List) {
+ fieldsValues, ok := m.terms.get(fieldName)
+ if !ok {
+ return roaring.EmptyPostingList
+ }
+ return fieldsValues.value.getRange(opts)
+}
diff --git a/pkg/index/inverted/mem_test.go b/pkg/index/inverted/mem_test.go
new file mode 100644
index 0000000..45117a7
--- /dev/null
+++ b/pkg/index/inverted/mem_test.go
@@ -0,0 +1,308 @@
+// 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 inverted
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/apache/skywalking-banyandb/api/common"
+ modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
+ "github.com/apache/skywalking-banyandb/pkg/convert"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting/roaring"
+)
+
+func TestMemTable_Initialize(t *testing.T) {
+ type args struct {
+ fields []FieldSpec
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr bool
+ }{
+ {
+ name: "golden path",
+ args: args{
+ fields: []FieldSpec{
+ {
+ Name: "service_name",
+ },
+ {
+ Name: "duration",
+ },
+ },
+ },
+ },
+ {
+ name: "fields absent",
+ wantErr: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ m := NewMemTable("sw")
+ var err error
+ if err = m.Initialize(tt.args.fields); (err != nil) != tt.wantErr {
+ t.Errorf("Initialize() error = %v, wantErr %v", err, tt.wantErr)
+ }
+ if err != nil {
+ return
+ }
+ assert.Equal(t, len(m.terms.repo), len(tt.args.fields))
+ })
+ }
+}
+
+func TestMemTable_Range(t *testing.T) {
+ type args struct {
+ fieldName []byte
+ opts *RangeOpts
+ }
+ m := NewMemTable("sw")
+ setUp(t, m)
+ tests := []struct {
+ name string
+ args args
+ wantList posting.List
+ }{
+ {
+ name: "in range",
+ args: args{
+ fieldName: []byte("duration"),
+ opts: &RangeOpts{
+ Lower: convert.Uint16ToBytes(100),
+ Upper: convert.Uint16ToBytes(500),
+ },
+ },
+ wantList: m.MatchTerms(&Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(200),
+ }),
+ },
+ {
+ name: "excludes edge",
+ args: args{
+ fieldName: []byte("duration"),
+ opts: &RangeOpts{
+ Lower: convert.Uint16ToBytes(50),
+ Upper: convert.Uint16ToBytes(1000),
+ },
+ },
+ wantList: union(m,
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(200),
+ },
+ ),
+ },
+ {
+ name: "includes lower",
+ args: args{
+ fieldName: []byte("duration"),
+ opts: &RangeOpts{
+ Lower: convert.Uint16ToBytes(50),
+ Upper: convert.Uint16ToBytes(1000),
+ IncludesLower: true,
+ },
+ },
+ wantList: union(m,
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(50),
+ },
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(200),
+ },
+ ),
+ },
+ {
+ name: "includes upper",
+ args: args{
+ fieldName: []byte("duration"),
+ opts: &RangeOpts{
+ Lower: convert.Uint16ToBytes(50),
+ Upper: convert.Uint16ToBytes(1000),
+ IncludesUpper: true,
+ },
+ },
+ wantList: union(m,
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(200),
+ },
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(1000),
+ },
+ ),
+ },
+ {
+ name: "includes edges",
+ args: args{
+ fieldName: []byte("duration"),
+ opts: &RangeOpts{
+ Lower: convert.Uint16ToBytes(50),
+ Upper: convert.Uint16ToBytes(1000),
+ IncludesUpper: true,
+ IncludesLower: true,
+ },
+ },
+ wantList: union(m,
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(50),
+ },
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(200),
+ },
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(1000),
+ },
+ ),
+ },
+ {
+ name: "match one",
+ args: args{
+ fieldName: []byte("duration"),
+ opts: &RangeOpts{
+ Lower: convert.Uint16ToBytes(200),
+ Upper: convert.Uint16ToBytes(200),
+ IncludesUpper: true,
+ IncludesLower: true,
+ },
+ },
+ wantList: union(m,
+ &Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(200),
+ },
+ ),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if gotList := m.Range(tt.args.fieldName, tt.args.opts); !reflect.DeepEqual(gotList, tt.wantList) {
+ t.Errorf("Range() = %v, want %v", gotList.Len(), tt.wantList.Len())
+ }
+ })
+ }
+}
+
+func TestMemTable_Iterator(t *testing.T) {
+ tester := assert.New(t)
+ type args struct {
+ fieldName []byte
+ orderType modelv2.QueryOrder_Sort
+ }
+ m := NewMemTable("sw")
+ setUp(t, m)
+ tests := []struct {
+ name string
+ args args
+ want [][]byte
+ }{
+ {
+ name: "sort asc",
+ args: args{
+ fieldName: []byte("duration"),
+ orderType: modelv2.QueryOrder_SORT_ASC,
+ },
+ want: [][]byte{convert.Uint16ToBytes(50), convert.Uint16ToBytes(200), convert.Uint16ToBytes(1000)},
+ },
+ {
+ name: "sort desc",
+ args: args{
+ fieldName: []byte("duration"),
+ orderType: modelv2.QueryOrder_SORT_DESC,
+ },
+ want: [][]byte{convert.Uint16ToBytes(1000), convert.Uint16ToBytes(200), convert.Uint16ToBytes(50)},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ iter := m.FieldIterator(tt.args.fieldName, tt.args.orderType)
+ tester.NotNil(iter)
+ var got [][]byte
+ defer func() {
+ _ = iter.Close()
+ }()
+ for iter.Next() {
+ got = append(got, iter.Val().key)
+ }
+ tester.Equal(tt.want, got)
+ })
+ }
+}
+
+func union(memTable *MemTable, fields ...*Field) posting.List {
+ result := roaring.NewPostingList()
+ for _, f := range fields {
+ _ = result.Union(memTable.MatchTerms(f))
+ }
+ return result
+}
+
+func setUp(t *testing.T, mt *MemTable) {
+ assert.NoError(t, mt.Initialize([]FieldSpec{
+ {
+ Name: "service_name",
+ },
+ {
+ Name: "duration",
+ },
+ }))
+ for i := 0; i < 100; i++ {
+ if i%2 == 0 {
+ assert.NoError(t, mt.Insert(&Field{
+ Name: []byte("service_name"),
+ Value: []byte("gateway"),
+ }, common.ItemID(i)))
+ } else {
+ assert.NoError(t, mt.Insert(&Field{
+ Name: []byte("service_name"),
+ Value: []byte("webpage"),
+ }, common.ItemID(i)))
+ }
+ }
+ for i := 100; i < 200; i++ {
+ switch {
+ case i%3 == 0:
+ assert.NoError(t, mt.Insert(&Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(50),
+ }, common.ItemID(i)))
+ case i%3 == 1:
+ assert.NoError(t, mt.Insert(&Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(200),
+ }, common.ItemID(i)))
+ case i%3 == 2:
+ assert.NoError(t, mt.Insert(&Field{
+ Name: []byte("duration"),
+ Value: convert.Uint16ToBytes(1000),
+ }, common.ItemID(i)))
+ }
+ }
+}
diff --git a/pkg/index/inverted/term_map.go b/pkg/index/inverted/term_map.go
new file mode 100644
index 0000000..c672239
--- /dev/null
+++ b/pkg/index/inverted/term_map.go
@@ -0,0 +1,161 @@
+// 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 inverted
+
+import (
+ "bytes"
+ "sort"
+ "sync"
+
+ "github.com/apache/skywalking-banyandb/api/common"
+ "github.com/apache/skywalking-banyandb/pkg/convert"
+ "github.com/apache/skywalking-banyandb/pkg/index"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting/roaring"
+)
+
+type termHashID uint64
+
+type postingMap struct {
+ repo map[termHashID]*index.PostingValue
+ mutex sync.RWMutex
+}
+
+func newPostingMap() *postingMap {
+ return &postingMap{
+ repo: make(map[termHashID]*index.PostingValue),
+ }
+}
+
+func (p *postingMap) put(key []byte, id common.ItemID) error {
+ list := p.getOrCreate(key)
+ list.Insert(id)
+ return nil
+}
+
+func (p *postingMap) getOrCreate(key []byte) posting.List {
+ list := p.get(key)
+ if list != roaring.EmptyPostingList {
+ return list
+ }
+ p.mutex.Lock()
+ defer p.mutex.Unlock()
+ hashedKey := termHashID(convert.Hash(key))
+ v := &index.PostingValue{
+ Key: key,
+ Value: roaring.NewPostingList(),
+ }
+ p.repo[hashedKey] = v
+ return v.Value
+}
+
+func (p *postingMap) get(key []byte) posting.List {
+ e := p.getEntry(key)
+ if e == nil {
+ return roaring.EmptyPostingList
+ }
+ return e.Value
+}
+
+func (p *postingMap) getEntry(key []byte) *index.PostingValue {
+ p.mutex.RLock()
+ defer p.mutex.RUnlock()
+ hashedKey := termHashID(convert.Hash(key))
+ v, ok := p.repo[hashedKey]
+ if !ok {
+ return nil
+ }
+ return v
+}
+
+func (p *postingMap) allValues() posting.List {
+ result := roaring.NewPostingList()
+ for _, value := range p.repo {
+ _ = result.Union(value.Value)
+ }
+ return result
+}
+
+func (p *postingMap) getRange(opts index.RangeOpts) posting.List {
+ switch bytes.Compare(opts.Upper, opts.Lower) {
+ case -1:
+ return roaring.EmptyPostingList
+ case 0:
+ if opts.IncludesUpper && opts.IncludesLower {
+ return p.get(opts.Upper)
+ }
+ return roaring.EmptyPostingList
+ }
+ p.mutex.RLock()
+ defer p.mutex.RUnlock()
+ keys := make(Asc, 0, len(p.repo))
+ for _, v := range p.repo {
+ keys = append(keys, v.Key)
+ }
+ sort.Sort(keys)
+ index := sort.Search(len(keys), func(i int) bool {
+ return bytes.Compare(keys[i], opts.Lower) >= 0
+ })
+ result := roaring.NewPostingList()
+ for i := index; i < len(keys); i++ {
+ k := keys[i]
+ switch {
+ case bytes.Equal(k, opts.Lower):
+ if opts.IncludesLower {
+ _ = result.Union(p.repo[termHashID(convert.Hash(k))].Value)
+ }
+ case bytes.Compare(k, opts.Upper) > 0:
+ break
+ case bytes.Equal(k, opts.Upper):
+ if opts.IncludesUpper {
+ _ = result.Union(p.repo[termHashID(convert.Hash(k))].Value)
+ }
+ default:
+ _ = result.Union(p.repo[termHashID(convert.Hash(k))].Value)
+ }
+ }
+ return result
+}
+
+type Asc [][]byte
+
+func (a Asc) Len() int {
+ return len(a)
+}
+
+func (a Asc) Less(i, j int) bool {
+ return bytes.Compare(a[i], a[j]) < 0
+}
+
+func (a Asc) Swap(i, j int) {
+ a[i], a[j] = a[j], a[i]
+}
+
+type Desc [][]byte
+
+func (d Desc) Len() int {
+ return len(d)
+}
+
+func (d Desc) Less(i, j int) bool {
+ return bytes.Compare(d[i], d[j]) > 0
+}
+
+func (d Desc) Swap(i, j int) {
+ d[i], d[j] = d[j], d[i]
+}
diff --git a/banyand/index/tsdb/field_map.go b/pkg/index/posting/posting.go
similarity index 51%
copy from banyand/index/tsdb/field_map.go
copy to pkg/index/posting/posting.go
index 4d89713..593e61c 100644
--- a/banyand/index/tsdb/field_map.go
+++ b/pkg/index/posting/posting.go
@@ -15,50 +15,61 @@
// specific language governing permissions and limitations
// under the License.
-package tsdb
+package posting
import (
"github.com/pkg/errors"
"github.com/apache/skywalking-banyandb/api/common"
- "github.com/apache/skywalking-banyandb/pkg/convert"
)
-var ErrFieldAbsent = errors.New("field doesn't exist")
+var ErrListEmpty = errors.New("postings list is empty")
-type fieldHashID uint64
+// List is a collection of common.ItemID.
+type List interface {
+ Contains(id common.ItemID) bool
-type fieldMap struct {
- repo map[fieldHashID]*fieldValue
-}
+ IsEmpty() bool
-func newFieldMap(initialSize int) *fieldMap {
- return &fieldMap{
- repo: make(map[fieldHashID]*fieldValue, initialSize),
- }
-}
+ Max() (common.ItemID, error)
-func (fm *fieldMap) createKey(key []byte) {
- fm.repo[fieldHashID(convert.Hash(key))] = &fieldValue{
- key: key,
- value: newPostingMap(),
- }
-}
+ Len() int
-func (fm *fieldMap) get(key []byte) (*fieldValue, bool) {
- v, ok := fm.repo[fieldHashID(convert.Hash(key))]
- return v, ok
-}
+ Iterator() Iterator
+
+ Clone() List
+
+ Equal(other List) bool
+
+ Insert(i common.ItemID)
+
+ Intersect(other List) error
+
+ Difference(other List) error
+
+ Union(other List) error
-func (fm *fieldMap) put(fv *Field, id common.ChunkID) error {
- pm, ok := fm.get(fv.Name)
- if !ok {
- return errors.Wrapf(ErrFieldAbsent, "filed Name:%s", fv.Name)
- }
- return pm.value.put(fv.Value, id)
+ UnionMany(others []List) error
+
+ AddIterator(iter Iterator) error
+
+ AddRange(min, max common.ItemID) error
+
+ RemoveRange(min, max common.ItemID) error
+
+ Reset()
+
+ ToSlice() []common.ItemID
+
+ Marshall() ([]byte, error)
+
+ Unmarshall(data []byte) error
}
-type fieldValue struct {
- key []byte
- value *postingMap
+type Iterator interface {
+ Next() bool
+
+ Current() common.ItemID
+
+ Close() error
}
diff --git a/pkg/index/posting/roaring/roaring.go b/pkg/index/posting/roaring/roaring.go
new file mode 100644
index 0000000..8f1f3d7
--- /dev/null
+++ b/pkg/index/posting/roaring/roaring.go
@@ -0,0 +1,214 @@
+// 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 roaring
+
+import (
+ "github.com/RoaringBitmap/roaring/roaring64"
+ "github.com/pkg/errors"
+
+ "github.com/apache/skywalking-banyandb/api/common"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+)
+
+var (
+ EmptyPostingList = NewPostingList()
+
+ ErrIntersectRoaringOnly = errors.New("Intersect only supported between roaringDocId sets")
+ ErrUnionRoaringOnly = errors.New("Union only supported between roaringDocId sets")
+ ErrDifferenceRoaringOnly = errors.New("Difference only supported between roaringDocId sets")
+)
+
+var _ posting.List = (*postingsList)(nil)
+
+// postingsList abstracts a Roaring Bitmap.
+type postingsList struct {
+ bitmap *roaring64.Bitmap
+}
+
+func (p *postingsList) Marshall() ([]byte, error) {
+ return p.bitmap.MarshalBinary()
+}
+
+func (p *postingsList) Unmarshall(data []byte) error {
+ return p.bitmap.UnmarshalBinary(data)
+}
+
+func NewPostingList() posting.List {
+ return &postingsList{
+ bitmap: roaring64.New(),
+ }
+}
+
+func NewPostingListWithInitialData(data ...uint64) posting.List {
+ list := NewPostingList()
+ for _, d := range data {
+ list.Insert(common.ItemID(d))
+ }
+ return list
+}
+
+func (p *postingsList) Contains(id common.ItemID) bool {
+ return p.bitmap.Contains(uint64(id))
+}
+
+func (p *postingsList) IsEmpty() bool {
+ return p.bitmap.IsEmpty()
+}
+
+func (p *postingsList) Max() (common.ItemID, error) {
+ if p.IsEmpty() {
+ return 0, posting.ErrListEmpty
+ }
+ return common.ItemID(p.bitmap.Maximum()), nil
+}
+
+func (p *postingsList) Len() int {
+ return int(p.bitmap.GetCardinality())
+}
+
+func (p *postingsList) Iterator() posting.Iterator {
+ return &roaringIterator{
+ iter: p.bitmap.Iterator(),
+ }
+}
+
+func (p *postingsList) Clone() posting.List {
+ return &postingsList{
+ bitmap: p.bitmap.Clone(),
+ }
+}
+
+func (p *postingsList) Equal(other posting.List) bool {
+ if p.Len() != other.Len() {
+ return false
+ }
+
+ iter := p.Iterator()
+ otherIter := other.Iterator()
+
+ for iter.Next() {
+ if !otherIter.Next() {
+ return false
+ }
+ if iter.Current() != otherIter.Current() {
+ return false
+ }
+ }
+
+ return true
+}
+
+func (p *postingsList) Insert(id common.ItemID) {
+ p.bitmap.Add(uint64(id))
+}
+
+func (p *postingsList) Intersect(other posting.List) error {
+ o, ok := other.(*postingsList)
+ if !ok {
+ return ErrIntersectRoaringOnly
+ }
+ p.bitmap.And(o.bitmap)
+ return nil
+}
+
+func (p *postingsList) Difference(other posting.List) error {
+ o, ok := other.(*postingsList)
+ if !ok {
+ return ErrDifferenceRoaringOnly
+ }
+ p.bitmap.AndNot(o.bitmap)
+ return nil
+}
+
+func (p *postingsList) Union(other posting.List) error {
+ o, ok := other.(*postingsList)
+ if !ok {
+ return ErrUnionRoaringOnly
+ }
+ p.bitmap.Or(o.bitmap)
+ return nil
+}
+
+func (p *postingsList) UnionMany(others []posting.List) error {
+ for _, other := range others {
+ err := p.Union(other)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (p *postingsList) AddIterator(iter posting.Iterator) error {
+ for iter.Next() {
+ p.Insert(iter.Current())
+ }
+ return nil
+}
+
+func (p *postingsList) AddRange(min, max common.ItemID) error {
+ for i := min; i < max; i++ {
+ p.bitmap.Add(uint64(i))
+ }
+ return nil
+}
+
+func (p *postingsList) RemoveRange(min, max common.ItemID) error {
+ for i := min; i < max; i++ {
+ p.bitmap.Remove(uint64(i))
+ }
+ return nil
+}
+
+func (p *postingsList) Reset() {
+ p.bitmap.Clear()
+}
+
+type roaringIterator struct {
+ iter roaring64.IntIterable64
+ current common.ItemID
+ closed bool
+}
+
+func (it *roaringIterator) Current() common.ItemID {
+ return it.current
+}
+
+func (it *roaringIterator) Next() bool {
+ if it.closed || !it.iter.HasNext() {
+ return false
+ }
+ v := it.iter.Next()
+ it.current = common.ItemID(v)
+ return true
+}
+
+func (it *roaringIterator) Close() error {
+ it.closed = true
+ return nil
+}
+
+func (p *postingsList) ToSlice() []common.ItemID {
+ iter := p.Iterator()
+ defer iter.Close()
+ s := make([]common.ItemID, 0, p.Len())
+ for iter.Next() {
+ s = append(s, iter.Current())
+ }
+ return s
+}
diff --git a/pkg/index/search.go b/pkg/index/search.go
new file mode 100644
index 0000000..3fa8bd4
--- /dev/null
+++ b/pkg/index/search.go
@@ -0,0 +1,335 @@
+// 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 index
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "strings"
+
+ "github.com/pkg/errors"
+
+ "github.com/apache/skywalking-banyandb/api/common"
+ modelv2 "github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v2"
+ "github.com/apache/skywalking-banyandb/pkg/index/posting"
+)
+
+var ErrNotRangeOperation = errors.New("this is not an range operation")
+
+type Executor interface {
+ Execute() (posting.List, error)
+}
+
+type Tree interface {
+ Executor
+}
+
+type Term struct {
+ SeriesID common.SeriesID
+ IndexRule string
+}
+
+func (t *Term) Marshal() []byte {
+ return bytes.Join([][]byte{
+ t.SeriesID.Marshal(),
+ []byte(t.IndexRule),
+ }, []byte(":"))
+}
+
+type Condition map[Term][]ConditionValue
+
+type ConditionValue struct {
+ Values [][]byte
+ Op modelv2.Condition_BinaryOp
+}
+
+func BuildTree(searcher Searcher, condMap Condition) (Tree, error) {
+ root := &andNode{
+ node: &node{
+ SubNodes: make([]Executor, 0),
+ searcher: searcher,
+ },
+ }
+ for term, conds := range condMap {
+ key := term.Marshal()
+ var rangeLeaf *rangeOp
+ for _, cond := range conds {
+ if rangeLeaf != nil && !rangeOP(cond.Op) {
+ return nil, errors.Wrapf(ErrNotRangeOperation, "op:%s", cond.Op.String())
+ }
+ if rangeOP(cond.Op) {
+ if rangeLeaf == nil {
+ rangeLeaf = root.addRangeLeaf(key)
+ }
+ opts := rangeLeaf.Opts
+ switch cond.Op {
+ case modelv2.Condition_BINARY_OP_GT:
+ opts.Lower = bytes.Join(cond.Values, nil)
+ case modelv2.Condition_BINARY_OP_GE:
+ opts.Lower = bytes.Join(cond.Values, nil)
+ opts.IncludesLower = true
+ case modelv2.Condition_BINARY_OP_LT:
+ opts.Upper = bytes.Join(cond.Values, nil)
+ case modelv2.Condition_BINARY_OP_LE:
+ opts.Upper = bytes.Join(cond.Values, nil)
+ opts.IncludesUpper = true
+ }
+ continue
+ }
+ switch cond.Op {
+ case modelv2.Condition_BINARY_OP_EQ:
+ root.addEq(key, cond.Values)
+ case modelv2.Condition_BINARY_OP_NE:
+ root.addNot(key, root.newEq(key, cond.Values))
+ case modelv2.Condition_BINARY_OP_HAVING:
+ n := root.addOrNode(len(cond.Values))
+ for _, v := range cond.Values {
+ n.addEq(key, [][]byte{v})
+ }
+ case modelv2.Condition_BINARY_OP_NOT_HAVING:
+ n := root.newOrNode(len(cond.Values))
+ for _, v := range cond.Values {
+ n.addEq(key, [][]byte{v})
+ }
+ root.addNot(key, n)
+ }
+ }
+ }
+ return root, nil
+}
+
+func rangeOP(op modelv2.Condition_BinaryOp) bool {
+ switch op {
+ case modelv2.Condition_BINARY_OP_GT,
+ modelv2.Condition_BINARY_OP_GE,
+ modelv2.Condition_BINARY_OP_LT,
+ modelv2.Condition_BINARY_OP_LE:
+ return true
+ }
+ return false
+}
+
+type logicalOP interface {
+ Executor
+ merge(posting.List) error
+}
+
+type node struct {
+ searcher Searcher
+ value posting.List
+ SubNodes []Executor `json:"sub_nodes,omitempty"`
+}
+
+func (n *node) newEq(key []byte, values [][]byte) *eq {
+ return &eq{
+ leaf: &leaf{
+ Key: key,
+ Values: values,
+ searcher: n.searcher,
+ },
+ }
+}
+
+func (n *node) addEq(key []byte, values [][]byte) {
+ n.SubNodes = append(n.SubNodes, n.newEq(key, values))
+}
+
+func (n *node) addNot(key []byte, inner Executor) {
+ n.SubNodes = append(n.SubNodes, ¬{
+ Key: key,
+ searcher: n.searcher,
+ Inner: inner,
+ })
+}
+
+func (n *node) addRangeLeaf(key []byte) *rangeOp {
+ r := &rangeOp{
+ leaf: &leaf{
+ Key: key,
+ searcher: n.searcher,
+ },
+ Opts: &RangeOpts{},
+ }
+ n.SubNodes = append(n.SubNodes, r)
+ return r
+}
+
+func (n *node) newOrNode(size int) *orNode {
+ return &orNode{
+ node: &node{
+ searcher: n.searcher,
+ SubNodes: make([]Executor, 0, size),
+ },
+ }
+}
+
+func (n *node) addOrNode(size int) *orNode {
+ on := n.newOrNode(size)
+ n.SubNodes = append(n.SubNodes, on)
+ return on
+}
+
+func (n *node) pop() (Executor, bool) {
+ if len(n.SubNodes) < 1 {
+ return nil, false
+ }
+ sn := n.SubNodes[0]
+ n.SubNodes = n.SubNodes[1:]
+ return sn, true
+}
+
+func execute(n *node, lp logicalOP) (posting.List, error) {
+ ex, hasNext := n.pop()
+ if !hasNext {
+ return n.value, nil
+ }
+ r, err := ex.Execute()
+ if err != nil {
+ return nil, err
+ }
+ if n.value == nil {
+ n.value = r
+ return lp.Execute()
+ }
+ err = lp.merge(r)
+ if err != nil {
+ return nil, err
+ }
+ if n.value.IsEmpty() {
+ return n.value, nil
+ }
+ return lp.Execute()
+}
+
+type andNode struct {
+ *node
+}
+
+func (an *andNode) merge(list posting.List) error {
+ return an.value.Intersect(list)
+}
+
+func (an *andNode) Execute() (posting.List, error) {
+ return execute(an.node, an)
+}
+
+func (an *andNode) MarshalJSON() ([]byte, error) {
+ data := make(map[string]interface{}, 1)
+ data["and"] = an.node.SubNodes
+ return json.Marshal(data)
+}
+
+type orNode struct {
+ *node
+}
+
+func (on *orNode) merge(list posting.List) error {
+ return on.value.Union(list)
+}
+
+func (on *orNode) Execute() (posting.List, error) {
+ return execute(on.node, on)
+}
+
+func (on *orNode) MarshalJSON() ([]byte, error) {
+ data := make(map[string]interface{}, 1)
+ data["or"] = on.node.SubNodes
+ return json.Marshal(data)
+}
+
+type leaf struct {
+ Executor
+ Key []byte
+ Values [][]byte
+ searcher Searcher
+}
+
+type not struct {
+ Executor
+ Key []byte
+ searcher Searcher
+ Inner Executor
+}
+
+func (n *not) Execute() (posting.List, error) {
+ all := n.searcher.MatchField([]byte(n.Key))
+ list, err := n.Inner.Execute()
+ if err != nil {
+ return nil, err
+ }
+ err = all.Difference(list)
+ return all, err
+}
+
+func (n *not) MarshalJSON() ([]byte, error) {
+ data := make(map[string]interface{}, 1)
+ data["not"] = n.Inner
+ return json.Marshal(data)
+}
+
+type eq struct {
+ *leaf
+}
+
+func (eq *eq) Execute() (posting.List, error) {
+ return eq.searcher.MatchTerms(Field{
+ Term: []byte(eq.Key),
+ Value: bytes.Join(eq.Values, nil),
+ }), nil
+}
+
+func (eq *eq) MarshalJSON() ([]byte, error) {
+ data := make(map[string]interface{}, 1)
+ data["eq"] = eq.leaf
+ return json.Marshal(data)
+}
+
+type rangeOp struct {
+ *leaf
+ Opts *RangeOpts
+}
+
+func (r *rangeOp) Execute() (posting.List, error) {
+ return r.searcher.Range(r.Key, *r.Opts), nil
+}
+
+func (r *rangeOp) MarshalJSON() ([]byte, error) {
+ data := make(map[string]interface{}, 1)
+ var builder strings.Builder
+ if r.Opts.Lower != nil {
+ if r.Opts.IncludesLower {
+ builder.WriteString("[")
+ } else {
+ builder.WriteString("(")
+ }
+ }
+ builder.WriteString(base64.StdEncoding.EncodeToString(r.Opts.Lower))
+ builder.WriteString(",")
+ builder.WriteString(base64.StdEncoding.EncodeToString(r.Opts.Upper))
+ if r.Opts.Upper != nil {
+ if r.Opts.IncludesUpper {
+ builder.WriteString("]")
+ } else {
+ builder.WriteString(")")
+ }
+ }
+ data["key"] = r.Key
+ data["range"] = builder.String()
+ return json.Marshal(data)
+}