Support new Match Query proto. (#70)

diff --git a/CHANGES.md b/CHANGES.md
index 690c255..d9857cd 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -8,6 +8,7 @@
 ### Features
 
 * Remove analyze DNS name to get/refresh IP for create connection.
+* Support new Match Query proto.
 
 0.7.0-rc3
 ------------------
diff --git a/README.md b/README.md
index 3df5d88..de01823 100644
--- a/README.md
+++ b/README.md
@@ -109,7 +109,7 @@
                                                           .setName("trace_id"))
                                      .addTags("trace_id")
                                      .setType(IndexRule.Type.TYPE_INVERTED)
-                                     .setAnalyzer(IndexRule.Analyzer.ANALYZER_UNSPECIFIED);
+                                     .setAnalyzer("simple");
 client.define(ir.build());
 ```
 
diff --git a/src/main/java/org/apache/skywalking/banyandb/v1/client/PairQueryCondition.java b/src/main/java/org/apache/skywalking/banyandb/v1/client/PairQueryCondition.java
index 4f8a9bb..84e90ef 100644
--- a/src/main/java/org/apache/skywalking/banyandb/v1/client/PairQueryCondition.java
+++ b/src/main/java/org/apache/skywalking/banyandb/v1/client/PairQueryCondition.java
@@ -19,6 +19,7 @@
 package org.apache.skywalking.banyandb.v1.client;
 
 import org.apache.skywalking.banyandb.model.v1.BanyandbModel;
+import org.apache.skywalking.banyandb.model.v1.BanyandbModel.Condition.MatchOption;
 
 import java.util.List;
 
@@ -28,19 +29,33 @@
 public abstract class PairQueryCondition<T> extends AbstractCriteria {
     protected final BanyandbModel.Condition.BinaryOp op;
     private final TagAndValue<T> tagAndValue;
+    private final MatchOption matchOption;
 
     private PairQueryCondition(BanyandbModel.Condition.BinaryOp op, TagAndValue<T> tagAndValue) {
         this.op = op;
         this.tagAndValue = tagAndValue;
+        this.matchOption = MatchOption.getDefaultInstance();
+    }
+
+    private PairQueryCondition(BanyandbModel.Condition.BinaryOp op,
+                               TagAndValue<T> tagAndValue,
+                               MatchOption matchOption) {
+        this.op = op;
+        this.tagAndValue = tagAndValue;
+        this.matchOption = matchOption;
     }
 
     @Override
     public BanyandbModel.Criteria build() {
+        BanyandbModel.Condition.Builder condition = BanyandbModel.Condition.newBuilder()
+                                                                           .setName(this.tagAndValue.getTagName())
+                                                                           .setOp(this.op)
+                                                                           .setValue(this.tagAndValue.buildTypedTagValue());
+        if (this.matchOption != null) {
+            condition.setMatchOption(this.matchOption);
+        }
         return BanyandbModel.Criteria.newBuilder()
-                .setCondition(BanyandbModel.Condition.newBuilder()
-                .setName(this.tagAndValue.getTagName())
-                .setOp(this.op)
-                .setValue(this.tagAndValue.buildTypedTagValue()).build())
+                .setCondition(condition.build())
                 .build();
     }
 
@@ -138,6 +153,10 @@
             super(op, new TagAndValue.StringTagPair(tagName, value));
         }
 
+        private StringQueryCondition(String tagName, BanyandbModel.Condition.BinaryOp op, String value, MatchOption matchOption) {
+            super(op, new TagAndValue.StringTagPair(tagName, value), matchOption);
+        }
+
         /**
          * Build a query condition for {@link String} type
          * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_EQ} as the relation
@@ -168,11 +187,24 @@
          *
          * @param tagName name of the tag
          * @param val     value of the tag
-         * @return a query that `String != value`
+         * @return a query that `String match value`
          */
         public static PairQueryCondition<String> match(String tagName, String val) {
             return new StringQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_MATCH, val);
         }
+
+        /**
+         * Build a query condition for {@link String} type
+         * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_MATCH} as the relation
+         *
+         * @param tagName name of the tag
+         * @param val     value of the tag
+         * @param matchOption set the specific match options
+         * @return a query that `match value`
+         */
+        public static PairQueryCondition<String> match(String tagName, String val, MatchOption matchOption) {
+            return new StringQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_MATCH, val, matchOption);
+        }
     }
 
     /**
diff --git a/src/main/proto/banyandb/v1/banyandb-database.proto b/src/main/proto/banyandb/v1/banyandb-database.proto
index 3f4aebe..de642b1 100644
--- a/src/main/proto/banyandb/v1/banyandb-database.proto
+++ b/src/main/proto/banyandb/v1/banyandb-database.proto
@@ -94,6 +94,8 @@
   EncodingMethod encoding_method = 3 [(validate.rules).enum.defined_only = true];
   // compression_method indicates how to compress data during writing
   CompressionMethod compression_method = 4 [(validate.rules).enum.defined_only = true];
+  // aggregate_function indicates how to aggregate data
+  model.v1.MeasureAggregate aggregate_function = 5;
 }
 
 // Measure intends to store data point
@@ -113,6 +115,13 @@
   google.protobuf.Timestamp updated_at = 6;
 }
 
+message MeasureAggregateFunction {
+  // type indicates the type of function argument
+  FieldType type = 1 [(validate.rules).enum.defined_only = true];
+  // aggregate_function indicates specific function for measure data
+  model.v1.MeasureAggregate aggregate_function = 2;
+}
+
 // TopNAggregation generates offline TopN statistics for a measure's TopN approximation
 message TopNAggregation {
   // metadata is the identity of an aggregation
@@ -157,19 +166,18 @@
   Type type = 3 [(validate.rules).enum.defined_only = true];
   // updated_at indicates when the IndexRule is updated
   google.protobuf.Timestamp updated_at = 4;
-  enum Analyzer {
-    ANALYZER_UNSPECIFIED = 0;
-    // Keyword analyzer is a “noop” analyzer which returns the entire input string as a single token.
-    ANALYZER_KEYWORD = 1;
-    // Standard analyzer provides grammar based tokenization
-    ANALYZER_STANDARD = 2;
-    // Simple analyzer breaks text into tokens at any non-letter character,
-    // such as numbers, spaces, hyphens and apostrophes, discards non-letter characters,
-    // and changes uppercase to lowercase.
-    ANALYZER_SIMPLE = 3;
-  }
+
   // analyzer analyzes tag value to support the full-text searching for TYPE_INVERTED indices.
-  Analyzer analyzer = 5;
+  // available analyzers are:
+  // - "standard" provides grammar based tokenization
+  // - "simple" breaks text into tokens at any non-letter character,
+  //            such as numbers, spaces, hyphens and apostrophes, discards non-letter characters,
+  //            and changes uppercase to lowercase.
+  // - "keyword" is a “noop” analyzer which returns the entire input string as a single token.
+  // - "url" breaks test into tokens at any non-letter and non-digit character.
+  string analyzer = 5;
+  // no_sort indicates whether the index is not for sorting.
+  bool no_sort = 6;
 }
 
 // Subject defines which stream or measure would generate indices
@@ -200,6 +208,7 @@
   google.protobuf.Timestamp updated_at = 6;
 }
 
+
 message StreamRegistryServiceCreateRequest {
   banyandb.database.v1.Stream stream = 1;
 }
diff --git a/src/main/proto/banyandb/v1/banyandb-model.proto b/src/main/proto/banyandb/v1/banyandb-model.proto
index 09824e3..5b4b2d3 100644
--- a/src/main/proto/banyandb/v1/banyandb-model.proto
+++ b/src/main/proto/banyandb/v1/banyandb-model.proto
@@ -25,10 +25,6 @@
 import "google/protobuf/struct.proto";
 import "validate/validate.proto";
 
-message ID {
-  string value = 1;
-}
-
 message Str {
   string value = 1;
 }
@@ -57,7 +53,6 @@
     Int int = 4;
     IntArray int_array = 5;
     bytes binary_data = 6;
-    ID id = 7;
   }
 }
 
@@ -84,6 +79,32 @@
   AGGREGATION_FUNCTION_SUM = 5;
 }
 
+enum MeasureAggregate {
+  MEASURE_AGGREGATE_UNSPECIFIED = 0;
+  // Calculate the minimum value of delta measures.
+  MEASURE_AGGREGATE_MIN = 1;
+  // Calculate the maximum value of delta measures.
+  MEASURE_AGGREGATE_MAX = 2;
+  // Count the number of delta measures.
+  MEASURE_AGGREGATE_COUNT = 3;
+  // Calculate the sum value of delta measures.
+  MEASURE_AGGREGATE_SUM = 4;
+  // Calculate the average value of delta measures.
+  MEASURE_AGGREGATE_AVG = 5;
+  // Calculate the percentage of delta measures, where the input matches with the condition.
+  MEASURE_AGGREGATE_PERCENT = 6;
+  // Calculate the ratio for measures, where the input matches with the condition.
+  MEASURE_AGGREGATE_RATE = 7;
+  // Calculate the histogram for delta measures.
+  MEASURE_AGGREGATE_HISTOGRAM = 8;
+  // Calculate the {p99, p95, p90, p75, p50} for delta measures.
+  MEASURE_AGGREGATE_PERCENTILE2 = 9;
+  // Calculate the apdex for delta measures.
+  MEASURE_AGGREGATE_APDEX = 10;
+  // Same like PERCENTILE2, little different on algorithm.
+  MEASURE_AGGREGATE_PERCENTILE = 11;
+}
+
 // 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.
@@ -126,6 +147,16 @@
   string name = 1;
   BinaryOp op = 2;
   TagValue value = 3;
+  message MatchOption {
+    string analyzer = 1;
+    enum Operator {
+      OPERATOR_UNSPECIFIED = 0;
+      OPERATOR_AND = 1;
+      OPERATOR_OR = 2;
+    }
+    Operator operator = 2;
+  }
+  MatchOption match_option = 4;
 }
 
 // tag_families are indexed.
@@ -168,7 +199,7 @@
     string name = 1;
     repeated string tags = 2;
   }
-  repeated TagFamily tag_families = 1 [(validate.rules).repeated.min_items = 1];
+  repeated TagFamily tag_families = 1;
 }
 
 // TimeRange is a range query for uint64,
@@ -186,4 +217,4 @@
   STATUS_NOT_FOUND = 3;
   STATUS_EXPIRED_SCHEMA = 4;
   STATUS_INTERNAL_ERROR = 5;
-}
\ No newline at end of file
+}
diff --git a/src/test/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClientTestCI.java b/src/test/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClientTestCI.java
index 1a68f98..c7cdd6c 100644
--- a/src/test/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClientTestCI.java
+++ b/src/test/java/org/apache/skywalking/banyandb/v1/client/BanyanDBClientTestCI.java
@@ -31,7 +31,7 @@
 public class BanyanDBClientTestCI {
     private static final String REGISTRY = "ghcr.io";
     private static final String IMAGE_NAME = "apache/skywalking-banyandb";
-    private static final String TAG = "a528a5d99745c8fa978c135b8bda2685c50cda95";
+    private static final String TAG = "9770bf48f9b88574683f56e2a137555cd68066d9";
 
     private static final String IMAGE = REGISTRY + "/" + IMAGE_NAME + ":" + TAG;
 
diff --git a/src/test/java/org/apache/skywalking/banyandb/v1/client/ITBanyanDBStreamQueryTests.java b/src/test/java/org/apache/skywalking/banyandb/v1/client/ITBanyanDBStreamQueryTests.java
index 5d8d255..c4f2573 100644
--- a/src/test/java/org/apache/skywalking/banyandb/v1/client/ITBanyanDBStreamQueryTests.java
+++ b/src/test/java/org/apache/skywalking/banyandb/v1/client/ITBanyanDBStreamQueryTests.java
@@ -213,8 +213,7 @@
                                                                   .setGroup("sw_record")
                                                                   .setName("trace_id"))
                                              .addTags("trace_id")
-                                             .setType(IndexRule.Type.TYPE_INVERTED)
-                                             .setAnalyzer(IndexRule.Analyzer.ANALYZER_UNSPECIFIED);
+                                             .setType(IndexRule.Type.TYPE_INVERTED);
         return builder.build();
     }
 
diff --git a/src/test/java/org/apache/skywalking/banyandb/v1/client/ITIndexRuleMetadataRegistryTest.java b/src/test/java/org/apache/skywalking/banyandb/v1/client/ITIndexRuleMetadataRegistryTest.java
index b6113cf..7463e72 100644
--- a/src/test/java/org/apache/skywalking/banyandb/v1/client/ITIndexRuleMetadataRegistryTest.java
+++ b/src/test/java/org/apache/skywalking/banyandb/v1/client/ITIndexRuleMetadataRegistryTest.java
@@ -87,12 +87,12 @@
     public void testIndexRuleRegistry_createAndUpdate() throws BanyanDBException {
         this.client.define(buildIndexRule());
         IndexRule before = client.findIndexRule("sw_record", "trace_id");
-        Assert.assertEquals(IndexRule.Analyzer.ANALYZER_SIMPLE, before.getAnalyzer());
-        IndexRule updatedIndexRule = before.toBuilder().setAnalyzer(IndexRule.Analyzer.ANALYZER_STANDARD).build();
+        Assert.assertEquals("simple", before.getAnalyzer());
+        IndexRule updatedIndexRule = before.toBuilder().setAnalyzer("standard").build();
         this.client.update(updatedIndexRule);
         IndexRule after = this.client.findIndexRule("sw_record", "trace_id");
         Assert.assertNotNull(after);
-        Assert.assertEquals(IndexRule.Analyzer.ANALYZER_STANDARD, after.getAnalyzer());
+        Assert.assertEquals("standard", after.getAnalyzer());
     }
 
     @Test
@@ -111,7 +111,7 @@
                                                                   .setName("trace_id"))
                                              .addTags("trace_id")
                                              .setType(IndexRule.Type.TYPE_INVERTED)
-            .setAnalyzer(IndexRule.Analyzer.ANALYZER_SIMPLE);
+            .setAnalyzer("simple");
         return builder.build();
     }
 }