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

haonan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 3247f48cd8 [IOTDB-3447] add some schema template function in python 
client (#6223)
3247f48cd8 is described below

commit 3247f48cd8f66e4e86ed3a5706ef884f0fa8880f
Author: Tom <[email protected]>
AuthorDate: Mon Jun 13 14:01:22 2022 +0800

    [IOTDB-3447] add some schema template function in python client (#6223)
---
 client-py/README.md                                |  60 +++++-
 client-py/SessionExample.py                        |  44 ++++-
 client-py/iotdb/Session.py                         | 219 ++++++++++++++++++++-
 client-py/iotdb/template/Template.py               |   5 +-
 client-py/iotdb/template/TemplateNode.py           |   3 +-
 .../Pair.py => template/TemplateQueryType.py}      |  25 ++-
 client-py/iotdb/tsfile/utils/Pair.py               |   4 +-
 client-py/tests/test_template.py                   | 130 +++++++++++-
 .../UserGuide/API/Programming-Python-Native-API.md |  60 +++++-
 .../UserGuide/API/Programming-Python-Native-API.md |  60 +++++-
 10 files changed, 582 insertions(+), 28 deletions(-)

diff --git a/client-py/README.md b/client-py/README.md
index 590bed9c1f..3166acacc4 100644
--- a/client-py/README.md
+++ b/client-py/README.md
@@ -282,13 +282,12 @@ The step for creating a metadata template is as follows
 3. Execute create schema template function
 
 ```python
-template = Template(name="treeTemplate_python", share_time=True)
+template = Template(name=template_name, share_time=True)
 
 i_node_gps = InternalNode(name="GPS", share_time=False)
 i_node_v = InternalNode(name="vehicle", share_time=True)
 m_node_x = MeasurementNode("x", TSDataType.FLOAT, TSEncoding.RLE, 
Compressor.SNAPPY)
 
-i_node_gps.add_child(m_node_x)
 i_node_gps.add_child(m_node_x)
 i_node_v.add_child(m_node_x)
 
@@ -298,6 +297,63 @@ template.add_template(m_node_x)
 
 session.create_schema_template(template)
 ```
+#### Modify Schema Template nodes
+Modify nodes in a template, the template must be already created. These are 
functions that add or delete some measurement nodes.
+* add node in template
+```python
+session.add_measurements_in_template(template_name, measurements_path, 
data_types, encodings, compressors, is_aligned)
+```
+
+* delete node in template
+```python
+session.delete_node_in_template(template_name, path)
+```
+
+#### Set Schema Template
+```python
+session.set_schema_template(template_name, prefix_path)
+```
+
+#### Uset Schema Template
+```python
+session.unset_schema_template(template_name, prefix_path)
+```
+
+#### Show Schema Template
+* Show all schema templates
+```python
+session.show_all_templates()
+```
+* Count all nodes in templates
+```python
+session.count_measurements_in_template(template_name)
+```
+
+* Judge whether the path is measurement or not in templates, This measurement 
must be in the template
+```python
+session.count_measurements_in_template(template_name, path)
+```
+
+* Judge whether the path is exist or not in templates, This path may not 
belong to the template
+```python
+session.is_path_exist_in_template(template_name, path)
+```
+
+* Show nodes under in schema template
+```python
+session.show_measurements_in_template(template_name)
+```
+
+* Show the path prefix where a schema template is set
+```python
+session.show_paths_template_set_on(template_name)
+```
+
+* Show the path prefix where a schema template is used (i.e. the time series 
has been created)
+```python
+session.show_paths_template_using_on(template_name)
+```
+
 #### Drop Schema Template
 Delete an existing metadata template,dropping an already set template is not 
supported
 ```python
diff --git a/client-py/SessionExample.py b/client-py/SessionExample.py
index 84e84c1bfb..61e82234db 100644
--- a/client-py/SessionExample.py
+++ b/client-py/SessionExample.py
@@ -354,12 +354,12 @@ session.create_schema_template(template)
 print("create template success template_python")
 
 # create internal node template
-template = Template(name="treeTemplate_python", share_time=True)
+template_name = "treeTemplate_python"
+template = Template(name=template_name, share_time=True)
 i_node_gps = InternalNode(name="GPS", share_time=False)
 i_node_v = InternalNode(name="vehicle", share_time=True)
 m_node_x = MeasurementNode("x", TSDataType.FLOAT, TSEncoding.RLE, 
Compressor.SNAPPY)
 
-i_node_gps.add_child(m_node_x)
 i_node_gps.add_child(m_node_x)
 i_node_v.add_child(m_node_x)
 template.add_template(i_node_gps)
@@ -369,9 +369,47 @@ template.add_template(m_node_x)
 session.create_schema_template(template)
 print("create template success treeTemplate_python}")
 
+print(session.is_measurement_in_template(template_name, "GPS"))
+print(session.is_measurement_in_template(template_name, "GPS.x"))
+print(session.show_all_templates())
+
+# # append schema template
+data_types = [TSDataType.FLOAT, TSDataType.FLOAT, TSDataType.DOUBLE]
+encoding_list = [TSEncoding.RLE, TSEncoding.RLE, TSEncoding.GORILLA]
+compressor_list = [Compressor.SNAPPY, Compressor.SNAPPY, Compressor.LZ4]
+
+measurements_aligned_path = ["aligned.s1", "aligned.s2", "aligned.s3"]
+session.add_measurements_in_template(
+    template_name,
+    measurements_aligned_path,
+    data_types,
+    encoding_list,
+    compressor_list,
+    is_aligned=True,
+)
+# session.drop_schema_template("add_template_python")
+measurements_aligned_path = ["unaligned.s1", "unaligned.s2", "unaligned.s3"]
+session.add_measurements_in_template(
+    template_name,
+    measurements_aligned_path,
+    data_types,
+    encoding_list,
+    compressor_list,
+    is_aligned=False,
+)
+session.delete_node_in_template(template_name, "aligned.s1")
+print(session.count_measurements_in_template(template_name))
+print(session.is_path_exist_in_template(template_name, "aligned.s1"))
+print(session.is_path_exist_in_template(template_name, "aligned.s2"))
+
+session.set_schema_template(template_name, "root.python.set")
+print(session.show_paths_template_using_on(template_name))
+print(session.show_paths_template_set_on(template_name))
+session.unset_schema_template(template_name, "root.python.set")
+
 # drop template
 session.drop_schema_template("template_python")
-session.drop_schema_template("treeTemplate_python")
+session.drop_schema_template(template_name)
 print("drop template success, template_python and treeTemplate_python")
 # close session connection.
 session.close()
diff --git a/client-py/iotdb/Session.py b/client-py/iotdb/Session.py
index 6f6832a902..5d451a66ab 100644
--- a/client-py/iotdb/Session.py
+++ b/client-py/iotdb/Session.py
@@ -25,6 +25,7 @@ from thrift.protocol import TBinaryProtocol, TCompactProtocol
 from thrift.transport import TSocket, TTransport
 
 from .template.Template import Template
+from .template.TemplateQueryType import TemplateQueryType
 from .thrift.rpc.TSIService import (
     Client,
     TSCreateTimeseriesReq,
@@ -41,6 +42,11 @@ from .thrift.rpc.TSIService import (
     TSInsertRecordsOfOneDeviceReq,
     TSCreateSchemaTemplateReq,
     TSDropSchemaTemplateReq,
+    TSAppendSchemaTemplateReq,
+    TSPruneSchemaTemplateReq,
+    TSSetSchemaTemplateReq,
+    TSUnsetSchemaTemplateReq,
+    TSQueryTemplateReq,
 )
 from .thrift.rpc.ttypes import (
     TSDeleteDataReq,
@@ -1181,9 +1187,9 @@ class Session(object):
     def create_schema_template(self, template: Template):
         """
         create schema template, users using this method should use the 
template class as an argument
-        :param template: The template contain multiple child node(see 
Template.py)
+        :param template: The template contains multiple child node(see 
Template.py)
         """
-        bytes_array = template.serialize()
+        bytes_array = template.serialize
         request = TSCreateSchemaTemplateReq(
             self.__session_id, template.get_name(), bytes_array
         )
@@ -1239,3 +1245,212 @@ class Session(object):
                 )
         except TTransport.TException as e:
             raise RuntimeError("execution of statement fails because: ", e)
+
+    def add_measurements_in_template(
+        self,
+        template_name: str,
+        measurements_path: list,
+        data_types: list,
+        encodings: list,
+        compressors: list,
+        is_aligned: bool = False,
+    ):
+        """
+        add measurements in the template, the template must already create. 
This function adds some measurements node.
+        :param template_name: template name, string list, like ["name_x", 
"name_y", "name_z"]
+        :param measurements_path: when ths is_aligned is True, recommend the 
name like a.b, like [python.x, python.y, iotdb.z]
+        :param data_types: using TSDataType(see IoTDBConstants.py)
+        :param encodings: using TSEncoding(see IoTDBConstants.py)
+        :param compressors: using Compressor(see IoTDBConstants.py)
+        :param is_aligned: True is aligned, False is unaligned
+        """
+        request = TSAppendSchemaTemplateReq(
+            self.__session_id,
+            template_name,
+            is_aligned,
+            measurements_path,
+            list(map(lambda x: x.value, data_types)),
+            list(map(lambda x: x.value, encodings)),
+            list(map(lambda x: x.value, compressors)),
+        )
+        status = self.__client.appendSchemaTemplate(request)
+        logger.debug(
+            "append unaligned template {} template name: {}".format(
+                self.__session_id, template_name
+            )
+        )
+        return Session.verify_success(status)
+
+    def delete_node_in_template(self, template_name: str, path: str):
+        """
+        delete a node in the template, this node must be already in the 
template
+        :param template_name: template name
+        :param path: measurements path
+        """
+        request = TSPruneSchemaTemplateReq(self.__session_id, template_name, 
path)
+        status = self.__client.pruneSchemaTemplate(request)
+        logger.debug(
+            "append unaligned template {} template name: {}".format(
+                self.__session_id, template_name
+            )
+        )
+        return Session.verify_success(status)
+
+    def set_schema_template(self, template_name, prefix_path):
+        """
+        set template in prefix path, template already exit, prefix path is not 
measurements
+        :param template_name: template name
+        :param prefix_path: prefix path
+        """
+        request = TSSetSchemaTemplateReq(self.__session_id, template_name, 
prefix_path)
+        status = self.__client.setSchemaTemplate(request)
+        logger.debug(
+            "set schema template to path{} template name: {}, path:{}".format(
+                self.__session_id, template_name, prefix_path
+            )
+        )
+        return Session.verify_success(status)
+
+    def unset_schema_template(self, template_name, prefix_path):
+        """
+        unset schema template from prefix path, this method unsetting the 
template from entities,
+        which have already inserted records using the template, is not 
supported.
+        :param template_name: template name
+        :param prefix_path:
+        """
+        request = TSUnsetSchemaTemplateReq(
+            self.__session_id, prefix_path, template_name
+        )
+        status = self.__client.unsetSchemaTemplate(request)
+        logger.debug(
+            "set schema template to path{} template name: {}, path:{}".format(
+                self.__session_id, template_name, prefix_path
+            )
+        )
+        return Session.verify_success(status)
+
+    def count_measurements_in_template(self, template_name: str):
+        """
+        drop schema template, this method should be used to the template unset 
anything
+        :param template_name: template name
+        """
+        request = TSQueryTemplateReq(
+            self.__session_id,
+            template_name,
+            TemplateQueryType.COUNT_MEASUREMENTS.value,
+        )
+        response = self.__client.querySchemaTemplate(request)
+        logger.debug(
+            "count measurements template {}, template name is {}, count is 
{}".format(
+                self.__session_id, template_name, response.measurements
+            )
+        )
+        return response.count
+
+    def is_measurement_in_template(self, template_name: str, path: str):
+        """
+        judge the node in the template is measurement or not, this node must 
in the template
+        :param template_name: template name
+        :param path:
+        """
+        request = TSQueryTemplateReq(
+            self.__session_id,
+            template_name,
+            TemplateQueryType.IS_MEASUREMENT.value,
+            path,
+        )
+        response = self.__client.querySchemaTemplate(request)
+        logger.debug(
+            "judge the path is measurement or not in template {}, template 
name is {}, result is {}".format(
+                self.__session_id, template_name, response.result
+            )
+        )
+        return response.result
+
+    def is_path_exist_in_template(self, template_name: str, path: str):
+        """
+        judge whether the node is a measurement or not in the template, this 
node must be in the template
+        :param template_name: template name
+        :param path:
+        """
+        request = TSQueryTemplateReq(
+            self.__session_id, template_name, 
TemplateQueryType.PATH_EXIST.value, path
+        )
+        response = self.__client.querySchemaTemplate(request)
+        logger.debug(
+            "judge the path is in template or not {}, template name is {}, 
result is {}".format(
+                self.__session_id, template_name, response.result
+            )
+        )
+        return response.result
+
+    def show_measurements_in_template(self, template_name: str, pattern: str = 
""):
+        """
+        show all measurements under the pattern in template
+        :param template_name: template name
+        :param pattern: parent path, if default, show all measurements
+        """
+        request = TSQueryTemplateReq(
+            self.__session_id,
+            template_name,
+            TemplateQueryType.SHOW_MEASUREMENTS.value,
+            pattern,
+        )
+        response = self.__client.querySchemaTemplate(request)
+        logger.debug(
+            "show measurements in template {}, template name is {}, result is 
{}".format(
+                self.__session_id, template_name, response.measurements
+            )
+        )
+        return response.measurements
+
+    def show_all_templates(self):
+        """
+        show all schema templates
+        """
+        request = TSQueryTemplateReq(
+            self.__session_id,
+            "",
+            TemplateQueryType.SHOW_TEMPLATES.value,
+        )
+        response = self.__client.querySchemaTemplate(request)
+        logger.debug(
+            "show all template {}, measurements is {}".format(
+                self.__session_id, response.measurements
+            )
+        )
+        return response.measurements
+
+    def show_paths_template_set_on(self, template_name):
+        """
+        show the path prefix where a schema template is set
+        :param template_name:
+        """
+        request = TSQueryTemplateReq(
+            self.__session_id, template_name, 
TemplateQueryType.SHOW_SET_TEMPLATES.value
+        )
+        response = self.__client.querySchemaTemplate(request)
+        logger.debug(
+            "show paths template set {}, on {}".format(
+                self.__session_id, response.measurements
+            )
+        )
+        return response.measurements
+
+    def show_paths_template_using_on(self, template_name):
+        """
+        show the path prefix where a schema template is used
+        :param template_name:
+        """
+        request = TSQueryTemplateReq(
+            self.__session_id,
+            template_name,
+            TemplateQueryType.SHOW_USING_TEMPLATES.value,
+        )
+        response = self.__client.querySchemaTemplate(request)
+        logger.debug(
+            "show paths template using {}, on {}".format(
+                self.__session_id, response.measurements
+            )
+        )
+        return response.measurements
diff --git a/client-py/iotdb/template/Template.py 
b/client-py/iotdb/template/Template.py
index d5137d3343..38f883d03f 100644
--- a/client-py/iotdb/template/Template.py
+++ b/client-py/iotdb/template/Template.py
@@ -48,6 +48,7 @@ class Template:
         if not self.children.pop(name, []):
             raise Exception("It is not a direct child of the template: " + 
name)
 
+    @property
     def serialize(self):
         format_str_list = [">"]
         values_tobe_packed = []
@@ -65,7 +66,7 @@ class Template:
             pair = stack.pop()
             prefix = pair.left
             cur_node = pair.right
-            full_path = list()
+            full_path = [prefix]
             if not cur_node.is_measurement():
                 if prefix != "":
                     full_path.append(TsFileConstant.PATH_SEPARATOR)
@@ -73,7 +74,7 @@ class Template:
                 if cur_node.is_share_time():
                     aligned_prefix.add("".join(full_path))
                 for child in cur_node.children:
-                    stack.append(Pair("".join(full_path), 
self.children[child]))
+                    stack.append(Pair("".join(full_path), 
cur_node.children[child]))
             else:
                 ReadWriteUtils.write(prefix, format_str_list, 
values_tobe_packed)
                 if prefix in aligned_prefix:
diff --git a/client-py/iotdb/template/TemplateNode.py 
b/client-py/iotdb/template/TemplateNode.py
index 62a6c70eac..6bab445394 100644
--- a/client-py/iotdb/template/TemplateNode.py
+++ b/client-py/iotdb/template/TemplateNode.py
@@ -21,6 +21,7 @@ class TemplateNode(object):
     """
     Template class, this class should be used to schema template node
     """
+
     def __init__(self, name):
         self.name = name
 
@@ -42,5 +43,5 @@ class TemplateNode(object):
     def is_share_time(self):
         return False
 
-    def serialize(self, buffer):
+    def serialize(self, *args, **kwargs):
         ...
diff --git a/client-py/iotdb/tsfile/utils/Pair.py 
b/client-py/iotdb/template/TemplateQueryType.py
similarity index 62%
copy from client-py/iotdb/tsfile/utils/Pair.py
copy to client-py/iotdb/template/TemplateQueryType.py
index 70bb3f7258..370d1c0a36 100644
--- a/client-py/iotdb/tsfile/utils/Pair.py
+++ b/client-py/iotdb/template/TemplateQueryType.py
@@ -16,11 +16,24 @@
 # under the License.
 #
 
-from iotdb.template.TemplateNode import TemplateNode
 
+from enum import Enum, unique
 
-class Pair:
-    def __init__(self, left: str, right: TemplateNode):
-        self.__serialVersionUID = -1398609631703707002
-        self.left = left
-        self.right = right
+
+@unique
+class TemplateQueryType(Enum):
+    COUNT_MEASUREMENTS = 0
+    IS_MEASUREMENT = 1
+    PATH_EXIST = 2
+    SHOW_MEASUREMENTS = 3
+    SHOW_TEMPLATES = 4
+    SHOW_SET_TEMPLATES = 5
+    SHOW_USING_TEMPLATES = 6
+
+    # this method is implemented to avoid the issue reported by:
+    # https://bugs.python.org/issue30545
+    def __eq__(self, other) -> bool:
+        return self.value == other.value
+
+    def __hash__(self):
+        return self.value
diff --git a/client-py/iotdb/tsfile/utils/Pair.py 
b/client-py/iotdb/tsfile/utils/Pair.py
index 70bb3f7258..f3603fa912 100644
--- a/client-py/iotdb/tsfile/utils/Pair.py
+++ b/client-py/iotdb/tsfile/utils/Pair.py
@@ -16,11 +16,9 @@
 # under the License.
 #
 
-from iotdb.template.TemplateNode import TemplateNode
-
 
 class Pair:
-    def __init__(self, left: str, right: TemplateNode):
+    def __init__(self, left: str, right):
         self.__serialVersionUID = -1398609631703707002
         self.left = left
         self.right = right
diff --git a/client-py/tests/test_template.py b/client-py/tests/test_template.py
index 0b8a84aefd..1dd328fdb2 100644
--- a/client-py/tests/test_template.py
+++ b/client-py/tests/test_template.py
@@ -29,7 +29,8 @@ def test_template_create():
         session = Session(db.get_container_host_ip(), 
db.get_exposed_port(6667))
         session.open(False)
 
-        template = Template(name="template_python", share_time=False)
+        measurement_template_name = "template_python"
+        template = Template(name=measurement_template_name, share_time=False)
         m_node_1 = MeasurementNode(
             name="s1",
             data_type=TSDataType.INT64,
@@ -53,22 +54,141 @@ def test_template_create():
         template.add_template(m_node_3)
         session.create_schema_template(template)
 
-        template = Template(name="treeTemplate_python", share_time=True)
+        assert 
session.show_measurements_in_template(measurement_template_name) == [
+            "s3",
+            "s1",
+            "s2",
+        ]
+        assert 
session.count_measurements_in_template(measurement_template_name) == 3
+        assert (
+            session.is_measurement_in_template(measurement_template_name, 
"s1") is True
+        )
+        assert (
+            session.is_path_exist_in_template(measurement_template_name, "s1") 
is True
+        )
+        assert (
+            session.is_path_exist_in_template(measurement_template_name, "s4") 
is False
+        )
+
+        session.delete_node_in_template(measurement_template_name, "s1")
+        assert 
session.show_measurements_in_template(measurement_template_name) == [
+            "s3",
+            "s2",
+        ]
+        assert 
session.count_measurements_in_template(measurement_template_name) == 2
+        assert (
+            session.is_path_exist_in_template(measurement_template_name, "s1") 
is False
+        )
+
+        tree_template_name = "treeTemplate_python"
+        template = Template(name=tree_template_name, share_time=True)
         i_node_gps = InternalNode(name="GPS", share_time=False)
         i_node_v = InternalNode(name="vehicle", share_time=True)
         m_node_x = MeasurementNode(
             "x", TSDataType.FLOAT, TSEncoding.RLE, Compressor.SNAPPY
         )
 
-        i_node_gps.add_child(m_node_x)
         i_node_gps.add_child(m_node_x)
         i_node_v.add_child(m_node_x)
         template.add_template(i_node_gps)
         template.add_template(i_node_v)
         template.add_template(m_node_x)
         session.create_schema_template(template)
+        assert session.show_measurements_in_template(tree_template_name) == [
+            "x",
+            "GPS.x",
+            "vehicle.x",
+        ]
+        assert session.count_measurements_in_template(tree_template_name) == 3
+
+        assert session.show_all_templates() == [
+            measurement_template_name,
+            tree_template_name,
+        ]
+        assert session.is_measurement_in_template(tree_template_name, "GPS") 
is False
+        assert session.is_measurement_in_template(tree_template_name, "GPS.x") 
is True
+
+        session.drop_schema_template(measurement_template_name)
+        session.drop_schema_template(tree_template_name)
+
+        session.close()
+
+
+def test_add_measurements_template():
+    with IoTDBContainer("iotdb:dev") as db:
+        db: IoTDBContainer
+        session = Session(db.get_container_host_ip(), 
db.get_exposed_port(6667))
+        session.open(False)
+
+        template_name = "add_template_python"
+        template = Template(name=template_name, share_time=False)
+        i_node_v = InternalNode(name="GPS", share_time=False)
+        i_node_gps_x = MeasurementNode(
+            "x", TSDataType.FLOAT, TSEncoding.RLE, Compressor.SNAPPY
+        )
+
+        i_node_v.add_child(i_node_gps_x)
+        template.add_template(i_node_v)
+        session.create_schema_template(template)
+
+        # # append schema template
+        data_types = [TSDataType.FLOAT, TSDataType.FLOAT, TSDataType.DOUBLE]
+        encoding_list = [TSEncoding.RLE, TSEncoding.RLE, TSEncoding.GORILLA]
+        compressor_list = [Compressor.SNAPPY, Compressor.SNAPPY, 
Compressor.LZ4]
+
+        measurements_aligned_path = ["aligned.s1", "aligned.s2", "aligned.s3"]
+        session.add_measurements_in_template(
+            template_name,
+            measurements_aligned_path,
+            data_types,
+            encoding_list,
+            compressor_list,
+            is_aligned=True,
+        )
+        # session.drop_schema_template("add_template_python")
+        measurements_aligned_path = ["unaligned.s1", "unaligned.s2", 
"unaligned.s3"]
+        session.add_measurements_in_template(
+            template_name,
+            measurements_aligned_path,
+            data_types,
+            encoding_list,
+            compressor_list,
+            is_aligned=False,
+        )
+        measurements_aligned_path = ["s1", "s2", "s3"]
+        session.add_measurements_in_template(
+            template_name,
+            measurements_aligned_path,
+            data_types,
+            encoding_list,
+            compressor_list,
+            is_aligned=False,
+        )
+
+        assert session.count_measurements_in_template(template_name) == 10
+        assert session.is_measurement_in_template(template_name, "GPS") is 
False
+        assert session.is_path_exist_in_template(template_name, "GPS.x") is 
True
+        assert session.is_path_exist_in_template(template_name, "x") is False
+
+        session.drop_schema_template(template_name)
+        session.close()
+
+
+def test_set_template():
+    with IoTDBContainer("iotdb:dev") as db:
+        db: IoTDBContainer
+        session = Session(db.get_container_host_ip(), 
db.get_exposed_port(6667))
+        session.open(False)
+
+        template_name = "set_template_python"
+        template = Template(name=template_name, share_time=False)
+        session.create_schema_template(template)
+
+        session.set_schema_template(template_name, "root.python.GPS")
 
-        session.drop_schema_template("template_python")
-        session.drop_schema_template("treeTemplate_python")
+        assert session.show_paths_template_set_on(template_name) == 
["root.python.GPS"]
+        assert session.show_paths_template_using_on(template_name) == []
 
+        session.unset_schema_template(template_name, "root.python.GPS")
+        session.drop_schema_template(template_name)
         session.close()
diff --git a/docs/UserGuide/API/Programming-Python-Native-API.md 
b/docs/UserGuide/API/Programming-Python-Native-API.md
index e3315de5b9..c3e39e6cd7 100644
--- a/docs/UserGuide/API/Programming-Python-Native-API.md
+++ b/docs/UserGuide/API/Programming-Python-Native-API.md
@@ -260,13 +260,12 @@ The step for creating a metadata template is as follows
 3. Execute create schema template function
 
 ```python
-template = Template(name="treeTemplate_python", share_time=True)
+template = Template(name=template_name, share_time=True)
 
 i_node_gps = InternalNode(name="GPS", share_time=False)
 i_node_v = InternalNode(name="vehicle", share_time=True)
 m_node_x = MeasurementNode("x", TSDataType.FLOAT, TSEncoding.RLE, 
Compressor.SNAPPY)
 
-i_node_gps.add_child(m_node_x)
 i_node_gps.add_child(m_node_x)
 i_node_v.add_child(m_node_x)
 
@@ -276,6 +275,63 @@ template.add_template(m_node_x)
 
 session.create_schema_template(template)
 ```
+#### Modify Schema Template measurements
+Modify measurements in a template, the template must be already created. These 
are functions that add or delete some measurement nodes.
+* add node in template
+```python
+session.add_measurements_in_template(template_name, measurements_path, 
data_types, encodings, compressors, is_aligned)
+```
+
+* delete node in template
+```python
+session.delete_node_in_template(template_name, path)
+```
+
+#### Set Schema Template
+```python
+session.set_schema_template(template_name, prefix_path)
+```
+
+#### Uset Schema Template
+```python
+session.unset_schema_template(template_name, prefix_path)
+```
+
+#### Show Schema Template
+* Show all schema templates
+```python
+session.show_all_templates()
+```
+* Count all measurements in templates
+```python
+session.count_measurements_in_template(template_name)
+```
+
+* Judge whether the path is measurement or not in templates, This measurement 
must be in the template
+```python
+session.count_measurements_in_template(template_name, path)
+```
+
+* Judge whether the path is exist or not in templates, This path may not 
belong to the template
+```python
+session.is_path_exist_in_template(template_name, path)
+```
+
+* Show nodes under in schema template
+```python
+session.show_measurements_in_template(template_name)
+```
+
+* Show the path prefix where a schema template is set
+```python
+session.show_paths_template_set_on(template_name)
+```
+
+* Show the path prefix where a schema template is used (i.e. the time series 
has been created)
+```python
+session.show_paths_template_using_on(template_name)
+```
+
 #### Drop Schema Template
 Delete an existing metadata template,dropping an already set template is not 
supported
 ```python
diff --git a/docs/zh/UserGuide/API/Programming-Python-Native-API.md 
b/docs/zh/UserGuide/API/Programming-Python-Native-API.md
index 23e66f3dd0..645e281008 100644
--- a/docs/zh/UserGuide/API/Programming-Python-Native-API.md
+++ b/docs/zh/UserGuide/API/Programming-Python-Native-API.md
@@ -254,13 +254,12 @@ session.execute_non_query_statement(sql)
 3. 调用创建元数据模版接口
 
 ```python
-template = Template(name="treeTemplate_python", share_time=True)
+template = Template(name=template_name, share_time=True)
 
 i_node_gps = InternalNode(name="GPS", share_time=False)
 i_node_v = InternalNode(name="vehicle", share_time=True)
 m_node_x = MeasurementNode("x", TSDataType.FLOAT, TSEncoding.RLE, 
Compressor.SNAPPY)
 
-i_node_gps.add_child(m_node_x)
 i_node_gps.add_child(m_node_x)
 i_node_v.add_child(m_node_x)
 
@@ -270,6 +269,63 @@ template.add_template(m_node_x)
 
 session.create_schema_template(template)
 ```
+#### 修改模版节点信息
+修改模版节点,其中修改的模版必须已经被创建。以下函数能够在已经存在的模版中增加或者删除物理量
+* 在模版中增加实体
+```python
+session.add_measurements_in_template(template_name, measurements_path, 
data_types, encodings, compressors, is_aligned)
+```
+
+* 在模版中删除物理量
+```python
+session.delete_node_in_template(template_name, path)
+```
+
+#### 挂载元数据模板
+```python
+session.set_schema_template(template_name, prefix_path)
+```
+
+#### 卸载元数据模版
+```python
+session.unset_schema_template(template_name, prefix_path)
+```
+
+#### 查看元数据模版
+* 查看所有的元数据模版
+```python
+session.show_all_templates()
+```
+* 查看元数据模版中的物理量个数
+```python
+session.count_measurements_in_template(template_name)
+```
+
+* 判断某个节点是否为物理量,该节点必须已经在元数据模版中
+```python
+session.count_measurements_in_template(template_name, path)
+```
+
+* 判断某个路径是否在元数据模版中,这个路径有可能不在元数据模版中
+```python
+session.is_path_exist_in_template(template_name, path)
+```
+
+* 查看某个元数据模板下的物理量
+```python
+session.show_measurements_in_template(template_name)
+```
+
+* 查看挂载了某个元数据模板的路径前缀
+```python
+session.show_paths_template_set_on(template_name)
+```
+
+* 查看使用了某个元数据模板(即序列已创建)的路径前缀
+```python
+session.show_paths_template_using_on(template_name)
+```
+
 #### 删除元数据模版
 删除已经存在的元数据模版,不支持删除已经挂载的模版
 ```python

Reply via email to