You are viewing a plain text version of this content. The canonical link for it is here.
Posted to reviews@iotdb.apache.org by GitBox <gi...@apache.org> on 2019/07/17 09:20:17 UTC

[GitHub] [incubator-iotdb] mikip65 commented on a change in pull request #247: TsFile Docs

mikip65 commented on a change in pull request #247: TsFile Docs
URL: https://github.com/apache/incubator-iotdb/pull/247#discussion_r304301304
 
 

 ##########
 File path: docs/Documentation/UserGuideV0.7.0/7-TsFile/2-Usage.md
 ##########
 @@ -0,0 +1,765 @@
+<!--
+
+    Licensed to the 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.  The 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.
+
+-->
+Now, you’re ready to start doing some awesome things with TsFile. This section demonstrates the detailed usage of TsFile.
+
+### Time-series Data
+A time-series is considered as a set of quadruples. A quadruple is defined as (deltaObject, measurement, time, value).
+
+* **deltaObject**: In many situations, a device which contains many sensors can be considered as a deltaObject.
+* **measurement**: A sensor can be considered as a measurement
+
+
+Table 1 illustrates a set of time-series data. The set showed in the following table contains one deltaObject named "device\_1" with three measurements named "sensor\_1", "sensor\_2" and "sensor\_3". 
+
+<center>
+<table style="text-align:center">
+	<tr><th colspan="6">device_1</th></tr>
+	<tr><th colspan="2">sensor_1</th><th colspan="2">sensor_2</th><th colspan="2">sensor_3</th></tr>
+	<tr><th>time</th><th>value</td><th>time</th><th>value</td><th>time</th><th>value</td>
+	<tr><td>1</td><td>1.2</td><td>1</td><td>20</td><td>2</td><td>50</td></tr>
+	<tr><td>3</td><td>1.4</td><td>2</td><td>20</td><td>4</td><td>51</td></tr>
+	<tr><td>5</td><td>1.1</td><td>3</td><td>21</td><td>6</td><td>52</td></tr>
+	<tr><td>7</td><td>1.8</td><td>4</td><td>20</td><td>8</td><td>53</td></tr>
+</table>
+<span>A set of time-series data</span>
+</center>
+
+**One Line of Data**: In many industrial applications, a device normally contains more than one sensor and these sensors may have values at a same timestamp, which is called one line of data. 
+
+Formally, one line of data consists of a `deltaObject_id`, a timestamp which indicates the milliseconds since January 1, 1970, 00:00:00, and several data pairs composed of `measurement_id` and corresponding `value`. All data pairs in one line belong to this `deltaObject_id` and have the same timestamp. If one of the `measurements` doesn't have a `value` in the `timestamp`, use a space instead(Actually, TsFile does not store null values). Its format is shown as follow:
+
+```
+deltaObject_id, timestamp, <measurement_id, value>...
+```
+
+An example is illustrated as follow. In this example, the data type of three measurements are  `INT32`, `FLOAT` and  `ENUMS` respectively.
+
+```
+device_1, 1490860659000, m1, 10, m2, 12.12, m3, MAN
+```
+
+
+### Writing TsFile
+
+#### Generate a TsFile File.
+A TsFile can be generated by following three steps and the complete code will be given in the section "Example for writing TsFile".
+
+* First, use the interface to construct a TsFile instance.
+	```
+	public TsFileWriter(File file) throws WriteProcessException, IOException
+	```
+	
+	**Parameters:**
+	
+	* file : The TsFile to write
+
+* Second, add measurements
+
+	```
+	public void addMeasurement(MeasurementDescriptor measurementDescriptor) throws WriteProcessException
+	```
+	
+	**Parameters:**
+	
+	* measurementDescriptor : The measurement information including name, data type and encoding
+	
+	Or use a json object
+	```
+	public void addMeasurementByJson(JSONObject measurement) throws WriteProcessException
+	```
+	**Parameters:**
+    	
+    * measurement : The Json object including name, data type, encoding, and compression type. See schema Json section 
+    below.
+    
+        > **Notice:** Although one measurement name can be used in multiple deltaObjects, the properties cannot be changed. I.e. 
+    it's not allowed to add one measurement name for multiple times with different type or encoding.
+    Here is a bad example:
+
+        ```
+        // The measurement "sensor_1" is float type
+        addMeasurement(new MeasurementSchema("sensor_1", TSDataType.FLOAT, TSEncoding.RLE));
+        // This call will throw a WriteProcessException exception
+        addMeasurement(new MeasurementSchema("sensor_1", TSDataType.INT32, TSEncoding.RLE));
+        ```
+* Third, write data continually.
+	
+	```
+	public void write(TSRecord record) throws IOException, WriteProcessException
+	```
+	
+	Use this interface to create a new TSRecord(a timestamp and device pair).
+	
+	```
+	public TSRecord(long timestamp, String deviceId)
+	```
+	Then create DataPoint(a measurement and value pair), and use the addTuple method to add the DataPoint to the correct
+	TsRecord.
+	
+* Finally, call `close` to finish this writing process. 
+	
+	```
+	public void close() throws IOException
+	```
+
+#### Format of Schema JSON
+`SchemaJSON` is a schema array specifying a list of allowable time series. The schema describes each measurement's `measurement_id`, `data_type`, `encoding`, `compression type` , and
+properties according to the specific data type.
+
+An example is shown as follow:
+
+``` json
+{
+    "schema": [
+        {
+            "measurement_id": "m1",
+            "data_type": "INT32",
+            "encoding": "RLE"
+        },
+        {
+            "measurement_id": "m2",
+            "data_type": "FLOAT",
+            "encoding": "TS_2DIFF",
+            "max_point_number": 2
+        },
+        {
+            "measurement_id": "m3",
+            "data_type": "ENUMS",
+            "encoding": "BITMAP",
+            "enum_values":["MAN","WOMAN"]
+        },
+        {
+            "measurement_id": "m4",
+            "data_type": "INT64",
+            "encoding": "RLE",            
+            "compressor": "SNAPPY"
+        }
+    ],
+}
+```
+`SchemaJSON` consists of a `JSONArray` of schema objects . For each schema object, which corresponds to a time series, its field description is shown as follow:
+
+| key      | is required|     description | allowed values|
+| :-------- | --------:| :------:| :------:|
+| measurement_id    |**required**	|name of the time series |any combination of letters, numbers and other symbols like `_` `.`  |
+| data_type    		|**required**	|data type|`BOOLEAN`, `INT32`, `INT64`, `FLOAT`, `DOUBLE`, `ENUM` and `TEXT`(namely `String`)|
+| encoding    		|**required**	| encoding approach for time domain. |`PLAIN`(for all data types), {`TS_2DIFF`, `RLE`}(for `INT32`, `INT64`, `FLOAT`, `DOUBLE`, `ENUM`), `BITMAP`(`ENUM`)|
+| compressor    		|**required**	| the type of compression.| `SNAPPY` and `UNCOMPRESSED`|
+| enum_values 		|required if `data_type` is `ENUM`	| the fields of `ENUM`  	|  in format of `["MAN","WOMAN"]`|
+| max\_point\_number    		|optional	| the number of reserved decimal digits. It's useful if the data type is `FLOAT`, `DOUBLE` or `BigDecimal`| natural number, defaults to 2|
+|max\_string\_length	|optional	| maximal length of string. It's useful if the data type is `TEXT`.  | positive integer, defaults to 128|
+
+
+
+#### Example for writing TsFile
+
+You should install TsFile to your local maven repository.
+
+See reference: [Installation](./1-Installation.md)
+
+
+
+##### Writing TsFile by using json schema
+
+```java
+package org.apache.iotdb.tsfile;
+
+import java.io.File;
+import java.io.IOException;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.write.TsFileWriter;
+import org.apache.iotdb.tsfile.write.record.TSRecord;
+import org.apache.iotdb.tsfile.write.record.datapoint.DataPoint;
+import org.apache.iotdb.tsfile.write.record.datapoint.FloatDataPoint;
+import org.apache.iotdb.tsfile.write.record.datapoint.IntDataPoint;
+import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+/**
+ * An example of writing data to TsFile
+ */
+public class TsFileWrite {
+  /**
+   * There are two ways to construct a TsFile instance,they generate the identical TsFile file.
+   * This method uses the first interface:
+   * public void addMeasurementByJson(JSONObject measurement) throws WriteProcessException
+   * The corresponding json string is provided below.
+   * {
+   *     "schema": [
+   *         {
+   *             "measurement_id": "sensor_1",
+   *             "data_type": "FLOAT",
+   *             "encoding": "RLE",
+   * 	         "compressor" : "UNCOMPRESSED"
+   *         },
+   *         {
+   *             "measurement_id": "sensor_2",
+   *             "data_type": "INT32",
+   *             "encoding": "TS_2DIFF",
+   * 	         "compressor" : "UNCOMPRESSED"
+   *         },
+   *         {
+   *             "measurement_id": "sensor_3",
+   *             "data_type": "INT32",
+   *             "encoding": "TS_2DIFF",
+   * 	         "compressor" : "UNCOMPRESSED"
+   *        }
+   *     ]
+   * }
+   */
+  public static void main(String args[]) {
+    try {
+         String path = "testWithJson.tsfile";
+         String jsonText = "{\n" +
+                 "    \"schema\": [\n" +
+                 "        {\n" +
+                 "            \"measurement_id\": \"sensor_1\",\n" +
+                 "            \"data_type\": \"FLOAT\",\n" +
+                 "            \"encoding\": \"RLE\",\n" +
+                 "            \"compressor\" : \"UNCOMPRESSED\"\n" +
+                 "        },\n" +
+                 "        {\n" +
+                 "            \"measurement_id\": \"sensor_2\",\n" +
+                 "            \"data_type\": \"INT32\",\n" +
+                 "            \"encoding\": \"TS_2DIFF\",\n" +
+                 "            \"compressor\" : \"UNCOMPRESSED\"\n" +
+                 "\n" +
+                 "        },\n" +
+                 "        {\n" +
+                 "            \"measurement_id\": \"sensor_3\",\n" +
+                 "            \"data_type\": \"INT32\",\n" +
+                 "            \"encoding\": \"TS_2DIFF\",        \n" +
+                 "            \"compressor\" : \"UNCOMPRESSED\"\n" +
+                 "\n" +
+                 "  }\n" +
+                 "    ]\n" +
+                 "}";
+         File f = new File(path);
+         if (f.exists()) {
+           f.delete();
+         }
+         TsFileWriter tsFileWriter = new TsFileWriter(f);
+         JSONObject j = JSONObject.parseObject(jsonText);
+         JSONArray schemas = j.getJSONArray("schema");
+         // add measurements into file schema
+         for (int i = 0; i < schemas.size(); ++i) {
+           tsFileWriter.addMeasurementByJson(schemas.getJSONObject(i));
+         }
+        // construct TSRecord
+        TSRecord tsRecord = new TSRecord(1, "device_1");
+        DataPoint dPoint1 = new FloatDataPoint("sensor_1", 1.2f);
+        DataPoint dPoint2 = new IntDataPoint("sensor_2", 20);
+        DataPoint dPoint3;
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+    
+        // write a TSRecord to TsFile
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(2, "device_1");
+        dPoint2 = new IntDataPoint("sensor_2", 20);
+        dPoint3 = new IntDataPoint("sensor_3", 50);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(3, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 1.4f);
+        dPoint2 = new IntDataPoint("sensor_2", 21);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(4, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 1.2f);
+        dPoint2 = new IntDataPoint("sensor_2", 20);
+        dPoint3 = new IntDataPoint("sensor_3", 51);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(6, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 7.2f);
+        dPoint2 = new IntDataPoint("sensor_2", 10);
+        dPoint3 = new IntDataPoint("sensor_3", 11);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(7, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 6.2f);
+        dPoint2 = new IntDataPoint("sensor_2", 20);
+        dPoint3 = new IntDataPoint("sensor_3", 21);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(8, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 9.2f);
+        dPoint2 = new IntDataPoint("sensor_2", 30);
+        dPoint3 = new IntDataPoint("sensor_3", 31);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        // close TsFile
+        tsFileWriter.close();        
+    } catch (Throwable e) {
+      e.printStackTrace();
+      System.out.println(e.getMessage());
+    }
+  }
+}
+
+```
+
+##### Writing TsFile directly without defining the schema by json
+
+```java
+package org.apache.iotdb.tsfile;
+
+import java.io.File;
+import java.io.IOException;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.write.TsFileWriter;
+import org.apache.iotdb.tsfile.write.record.TSRecord;
+import org.apache.iotdb.tsfile.write.record.datapoint.DataPoint;
+import org.apache.iotdb.tsfile.write.record.datapoint.FloatDataPoint;
+import org.apache.iotdb.tsfile.write.record.datapoint.IntDataPoint;
+import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+/**
+ * An example of writing data to TsFile
+ */
+public class TsFileWrite {
+   /**
+    * There are two ways to construct a TsFile instance,they generate the identical TsFile file.
+    * This method uses the second interface:
+    * public void addMeasurement(MeasurementSchema MeasurementSchema) throws WriteProcessException
+    * The measurements are identical to the json string provided above.
+    */
+  public static void main(String args[]) {
+    try {
+        String path = "testDirect.tsfile";
+        File f = new File(path);
+        if (f.exists()) {
+          f.delete();
+        }
+        TsFileWriter tsFileWriter = new TsFileWriter(f);
+    
+        // add measurements into file schema
+        tsFileWriter
+                .addMeasurement(new MeasurementSchema("sensor_1", TSDataType.FLOAT, TSEncoding.RLE));
+        tsFileWriter
+                .addMeasurement(new MeasurementSchema("sensor_2", TSDataType.INT32, TSEncoding.TS_2DIFF));
+        tsFileWriter
+                .addMeasurement(new MeasurementSchema("sensor_3", TSDataType.INT32, TSEncoding.TS_2DIFF));
+        // construct TSRecord
+        TSRecord tsRecord = new TSRecord(1, "device_1");
+        DataPoint dPoint1 = new FloatDataPoint("sensor_1", 1.2f);
+        DataPoint dPoint2 = new IntDataPoint("sensor_2", 20);
+        DataPoint dPoint3;
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+    
+        // write a TSRecord to TsFile
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(2, "device_1");
+        dPoint2 = new IntDataPoint("sensor_2", 20);
+        dPoint3 = new IntDataPoint("sensor_3", 50);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(3, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 1.4f);
+        dPoint2 = new IntDataPoint("sensor_2", 21);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(4, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 1.2f);
+        dPoint2 = new IntDataPoint("sensor_2", 20);
+        dPoint3 = new IntDataPoint("sensor_3", 51);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(6, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 7.2f);
+        dPoint2 = new IntDataPoint("sensor_2", 10);
+        dPoint3 = new IntDataPoint("sensor_3", 11);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(7, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 6.2f);
+        dPoint2 = new IntDataPoint("sensor_2", 20);
+        dPoint3 = new IntDataPoint("sensor_3", 21);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        tsRecord = new TSRecord(8, "device_1");
+        dPoint1 = new FloatDataPoint("sensor_1", 9.2f);
+        dPoint2 = new IntDataPoint("sensor_2", 30);
+        dPoint3 = new IntDataPoint("sensor_3", 31);
+        tsRecord.addTuple(dPoint1);
+        tsRecord.addTuple(dPoint2);
+        tsRecord.addTuple(dPoint3);
+        tsFileWriter.write(tsRecord);
+    
+        // close TsFile
+        tsFileWriter.close();        
+    } catch (Throwable e) {
+      e.printStackTrace();
+      System.out.println(e.getMessage());
+    }
+  }
+}
+```
+
+### Interface for Reading TsFile
+
+#### Before the Start
+
+The set of time-series data in section "Time-series Data" is used here for a concrete introduction in this section. The set showed in the following table contains one deltaObject named "device\_1" with three measurements named "sensor\_1", "sensor\_2" and "sensor\_3". And the measurements has been simplified to do a simple illustration, which contains only 4 time-value pairs each.
+
+<center>
+<table style="text-align:center">
+	<tr><th colspan="6">device_1</th></tr>
+	<tr><th colspan="2">sensor_1</th><th colspan="2">sensor_2</th><th colspan="2">sensor_3</th></tr>
+	<tr><th>time</th><th>value</td><th>time</th><th>value</td><th>time</th><th>value</td>
+	<tr><td>1</td><td>1.2</td><td>1</td><td>20</td><td>2</td><td>50</td></tr>
+	<tr><td>3</td><td>1.4</td><td>2</td><td>20</td><td>4</td><td>51</td></tr>
+	<tr><td>5</td><td>1.1</td><td>3</td><td>21</td><td>6</td><td>52</td></tr>
+	<tr><td>7</td><td>1.8</td><td>4</td><td>20</td><td>8</td><td>53</td></tr>
+</table>
+<span>A set of time-series data</span>
+</center>
+
+#### Definition of Path
+
+A path represents a series instance in TsFile. In the example given above, "device\_1.sensor\_1" is a path.
+
+In read interfaces, The parameter ```paths``` indicates the measurements to be selected.
+
+Path instance can be easily constructed through the class ```Path```. For example:
+
+```
+Path p = new Path("device_1.sensor_1");
+```
+
+We will pass an ArrayList of paths for final query call to support multiple paths.
+
+```
+List<Path> paths = new ArrayList<Path>();
+paths.add(new Path("device_1.sensor_1"));
+paths.add(new Path("device_1.sensor_3"));
+```
+
+> **Notice:** When constructing a Path, the format of the parameter should be "\<deltaObjectId\>.\<measurementId\>"
+
+
+#### Definition of Filter
+
+##### Usage Scenario
+Filter is used in TsFile reading process to select data. 
+
+##### IExpression
+The `IExpression` is a filter expression interface and it will be passed to our final query call.
+We create one or more filter expressions and may use binary filter operators to link them to our final expression.
+
+* **Create a Filter Expression**
+	
+	There are two types of filters.
+	
+	 * TimeFilter: A filter for `time` in time-series data.
+	 	```
+	 	IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter);
+	 	```
+	 	Use the following relationships to get a `TimeFilter` object (value is a long int variable).
+	    <center>
+        <table style="text-align:center">
+        	<tr><th>Relationship</th><th>Description</td></tr>
+        	<tr><td>TimeFilter.eq(value)</td><td>Choose the time equal to the value</td>
+        	<tr><td>TimeFilter.lt(value)</td><td>Choose the time less than the value</td>
+        	<tr><td>TimeFilter.gt(value)</td><td>Choose the time greater than the value</td>
+        	<tr><td>TimeFilter.ltEq(value)</td><td>Choose the time less than or equal to the value</td>
+        	<tr><td>TimeFilter.gtEq(value)</td><td>Choose the time greater than or equal to the value</td>
+        	<tr><td>TimeFilter.notEq(value)</td><td>Choose the time not equal to the value</td>
+        	<tr><td>TimeFilter.not(TimeFilter)</td><td>Choose the time not satisfy another TimeFilter</td>
+        </table>
+        </center>
+	 	
+	 * ValueFilter: A filter for `value` in time-series data.
+	 	
+	 	```
+	 	IExpression valueFilterExpr = new SingleSeriesExpression(Path, ValueFilter);
+	 	```
+		The usage of  `ValueFilter` is the same as using `TimeFilter`, just to make sure that the type of the value
+		equal to the sensor(defined in the path).
+
+* **Binary Filter Operators**
+
+	Binary filter operators can be used to link two single expressions.
+
+	 * BinaryExpression.and(Expression, Expression): Choose the value satisfy for both expressions.
+	 * BinaryExpression.or(Expression, Expression): Choose the value satisfy for at least one expression.
+	 
+
+##### Filter Expression Examples
+
+* **TimeFilterExpression Examples**
+
+	```
+	IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.eq(15)); // series time = 15
+
+	```
+	```
+	IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.ltEq(15)); // series time <= 15
+
+	```
+	```
+	IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.lt(15)); // series time < 15
+
+	```
+	```
+	IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.gtEq(15)); // series time >= 15
+
+	```
+	```
+	IExpression timeFilterExpr = new GlobalTimeExpression(TimeFilter.notEq(15)); // series time != 15
+
+	```
+	```
+	IExpression timeFilterExpr = BinaryExpression.and(new GlobalTimeExpression(TimeFilter.gtEq(15L)),
+                                             new GlobalTimeExpression(TimeFilter.lt(25L))); // 15 <= series time < 25
+	```
+	```
+	IExpression timeFilterExpr = BinaryExpression.or(new GlobalTimeExpression(TimeFilter.gtEq(15L)),
+                                             new GlobalTimeExpression(TimeFilter.lt(25L))); // series time >= 15 or series time < 25
+	```
+#### Read Interface
+
+First, we open the TsFile and get a `ReadOnlyTsFile` instance from a file path string `path`.
+
+```
+TsFileSequenceReader reader = new TsFileSequenceReader(path);
+   
+ReadOnlyTsFile readTsFile = new ReadOnlyTsFile(reader);
+```
+Next, we prepare the path array and query expression, then get final `QueryExpression` object by this interface:
+
+```
+QueryExpression queryExpression = QueryExpression.create(paths, statement);
+```
+
+The ReadOnlyTsFile class has two `query` method to perform a query.
+* **Method 1**
+
+	```
+	public QueryDataSet query(QueryExpression queryExpression) throws IOException
+	```
+
+* **Method 2**
+
+	```
+	public QueryDataSet query(QueryExpression queryExpression, long partitionStartOffset, long partitionEndOffset) throws IOException
+	```
+
+	This method is designed for advanced applications such as the TsFile-Spark Connector.
+
+	* **params** : For method 2, two additional parameters are added to support partial query:
+		*  ```partitionStartOffset```: start offset for a TsFile
+		*  ```partitionEndOffset```: end offset for a TsFile
+
+		> **What is Partial Query ?**
+		>
+		> In some distributed file systems(e.g. HDFS), a file is split into severval parts which are called "Blocks" and stored in different nodes. Executing a query paralleled in each nodes involved makes better efficiency. Thus Partial Query is needed. Paritial Query only selects the results stored in the part split by ```QueryConstant.PARTITION_START_OFFSET``` and ```QueryConstant.PARTITION_END_OFFSET``` for a TsFile.
+
+#### QueryDataset Interface
+
+The query performed above will return a `QueryDataset` object.
+
+Here's the useful interfaces for user.
+
+
+* `bool hasNext();`
+
+    Return true if this dataset still has elements.
+* `List<Path> getPaths()`
+
+    Get the paths in this data set.
+* `List<TSDataType> getDataTypes();` 
+
+   Get the data types. The class TSDataType is an enum class, the value will be one of the following:
+   
+       BOOLEAN,
+       INT32,
+       INT64,
+       FLOAT,
+       DOUBLE,
+       TEXT;
+ * `RowRecord next() throws IOException;`
+ 
+    Get the next record.
+    
+    The class `RowRecord` consists of a `long` timestamp and a `List<Field>` for data in different sensors,
+     we can use two getter methods to get them.
+     
+    ```
+    long getTimestamp();
+    List<Field> getFields();
+    ```
+    
+    To get data from one Field, use these method:
+    
+    ```
+    TSDataType getDataType();
+    Object getObjectValue();
+    ```
+
+#### Example for reading an existing TsFile
+
+You should install TsFile to your local maven repository.
+
+See reference: [Installation](./1-Installation.md)
+
+
+```java
+/**
+ * Licensed to the 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.  The 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.
+ */
 
 Review comment:
   I saw there were license statements in other .md files.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services