Prerequisites
- A latest version of Ultipa V4.3 server running, such as, on cluster 192.168.1.85:60061,192.168.1.86:60061,192.168.1.87:60061
- The latest Ultipa Python V4.3 driver installed, see Installation for details
Make a Connection
To connect to a running Ultipa server instance, specify at least the login information of the host using an instance of UltipaConfig
and pass that into Connection.NewConnection()
.
The UltipaConfig
will connect to graphset default on the specified host if defaultGraph is not specified:
Connect to a Cluster
from ultipa import Connection, UltipaConfig
ultipaConfig = UltipaConfig()
ultipaConfig.hosts = ["192.168.1.85:60061", "192.168.1.86:60061", "192.168.1.87:60061"]
ultipaConfig.username = "***"
ultipaConfig.password = "***"
connection = Connection.NewConnection(defaultConfig=ultipaConfig)
Connect to Ultipa Cloud
from ultipa import Connection, UltipaConfig
ultipaConfig = UltipaConfig()
ultipaConfig.hosts = ["https://xaznryn5s.us-east-1.cloud.ultipa.com:60010"]
ultipaConfig.username = "***"
ultipaConfig.password = "***"
ultipaConfig.defaultGraph = "amz"
connection = Connection.NewConnection(defaultConfig=ultipaConfig)
See documentations UltipaConfig and Connection for details.
Once a connection is made, any modifications on the UltipaConfig
instance will automatically update this connection.
The following code switches the graphset used by the connection to amz from whichever it was:
ultipaConfig.defaultGraph = "amz"
Use an instance of LoggerConfig
to specify the logger information and update the UltipaConfig
instance. Below code snippet sets the logger to output the activities of the connection to the console:
from ultipa.utils.logger import LoggerConfig
loggerConfig = LoggerConfig(name="myLog", isStream=True)
ultipaConfig.uqlLoggerConfig = loggerConfig
connection.test().Print()
Modifications on the LoggerConfig
instance also update the UltipaConfig
instance and the connection in real-time. Below code snippet enables the activities of the connection to be written to a file:
loggerConfig.filename = "myLogFile"
loggerConfig.isWriteToFile = True
See documentation LoggerConfig for details.
Create GraphSet
Use one of the following approaches to create new graphset in the connected Ultipa server:
- Via interface (one graphset): specify the name and description of the graphset using data class
Graph
and pass intocreateGraph()
- Via UQL (multiple graphsets): pass the UQL string of creating graphset into
uql()
The following code creates graphset graph1 via interface:
from ultipa import GraphInfo
connection.createGraph(graph=GraphInfo(
name="graph1",
description="graphset created via interface"
))
The following code creates graphsets graph2, graph3 and graph4 via UQL:
connection.uql("create().graph('graph2','graphset created via uql').graph('graph3','graphset created via uql').graph('graph4','graphset created via uql')")
See documentation Graph, createGraph() and uql() for details.
See later section for details on showing, altering and dropping graphset.
Define Graph Model
Graph model refers to the definition of schema of metadata and the properties each schema has.
Create Schema
Node schema default and edge schema default are auto-created on the initialization of a graphset. To create schema in the connected graphset, use one of the following approaches:
- Via interface (one schema): specify the name, DB type (node or edge) and description of the schema using data class
Schema
and pass intocreateSchema()
- Via UQL (multiple schemas): pass the UQL string of creating schema into
uql()
The following code creates node schema student in the connected graphset via interface:
from ultipa import Schema
from ultipa import DBType
connection.createSchema(schema=Schema(
name="student",
dbType=DBType.DBNODE,
description="in the connected graphset"
))
See documentation Schema, createSchema() and DBType for details.
If the target graphset where the schema should be created is not the graphset being connected, either switch the connection to the target graphset via the UltipaConfig
instance, or specify the target graphset using RequestConfig
when calling createSchema()
.
The following code creates node schema student in graphset graph1 via interface:
from ultipag import RequestConfig
connection.createSchema(
schema=Schema(
name="student",
dbType=DBType.DBNODE,
description="in graph1"
),
requestConfig=RequestConfig(graphName="graph1")
)
See documentation RequestConfig for details.
Note that
RequestConfig
only specify the target graphset against which a non-insert operation would be executed, without changing the graphset of the connection.
The following code creates node schema professor, edge schema mentor and assist in graphset graph1 via UQL:
connection.uql(
uql="create().node_schema('professor').edge_schema('mentor').edge_schema('assist')",
requestConfig=RequestConfig(graphName="graph1")
)
See later section for details on showing, altering and dropping schema.
Create Property
To create custom property for a designated schema in the connected graphset, use one of the following approaches:
- Via interface (one property): pass the DB type, schema name and property information (using data class
Property
) intocreateProperty()
- Via UQL (multiple properties): pass the UQL string of creating property into
uql()
The following code creates property name for node schema student in graph1 via interface:
from ultipa import Property
from ultipa import PropertyTypeStr
connection.createProperty(
dbType=DBType.DBNODE,
schema="student",
prop=Property(
name="name",
type=PropertyTypeStr.PROPERTY_STRING,
description="student name"
),
requestConfig=RequestConfig("graph1")
)
See documentation Property, createProperty() and PropertyTypeStr for details.
Consider below schemas and their properties:
DB Type | Schema | Property | Data Type |
---|---|---|---|
node | student | age | int32 |
node | professor | name | string |
node | professor | age | int32 |
edge | mentor | year | int32 |
edge | assist | year | int32 |
The following code creates all the above properties in graphset graph1 via UQL:
connection.uql(
uql="create().node_property(@student,'age',int32).node_property(@professor,'name',string).node_property(@professor,'age',int32).edge_property(@mentor,'year',int32).edge_property(@assist,'year',int32)",
requestConfig=RequestConfig("graph1")
)
See later section for details on showing, altering and dropping property.
Insert Metadata
Metadata refers to nodes and edges in the graph. A list of metadata with elements built by data class EntityRow
should be ready before the insert operation.
See documentation EntityRow for details.
Auto
Below interfaces allow inserting metadata from different schemas at a time:
insertNodesBatchAuto()
insertEdgesBatchAuto()
When using the above two interfaces, the information of schema should be specified for each metadata when building the metadata list using EntityRow
.
See documentation EntityRow for details.
The following code inserts student 'S003' and professor 'P001' into their respective schemas in graph1:
from ultipa import EntityRow
from ultipa import InsertConfig
from ultipa import InsertType
mixedNodeList = [
EntityRow(id="S003", schema="student", values={"name": "Jason", "age": 27}),
EntityRow(id="P001", schema="professor", values={"name": "Peter", "age": 41})
]
auto_insert_node_result = connection.insertNodesBatchAuto(
nodes=mixedNodeList,
config=InsertConfig(
insertType=InsertType.NORMAL,
graphName="graph1"
)
)
auto_insert_node_result.Print()
See documentation insertNodesBatchAuto(), InsertConfig and InsertType for details.
InsertConfig
specifies the insert type (insert/upsert/overwrite) and connection information (such as target graphset, etc.) of an insert operation. Similar toRequestConfig
, it will not change the connection profile specified by theUltipaConfig
instance.
The following code inserts a list of edges into schemas mentor and assist in graph1:
mixedEdgeList = [
EntityRow(schema="assist", from_id="S001", to_id="P001", values={"year": 2022}),
EntityRow(schema="mentor", from_id="P001", to_id="S002", values={"year": 2021}),
EntityRow(schema="mentor", from_id="P001", to_id="S003", values={"year": 2023})
]
auto_insert_edge_result1 = connection.insertEdgesBatchAuto(
edges=mixedEdgeList,
config=InsertConfig(
insertType=InsertType.NORMAL,
graphName="graph1")
)
auto_insert_edge_result1.Print()
auto_insert_edge_result2 = connection.insertEdgesBatchAuto(
edges=mixedEdgeList,
config=InsertConfig(
insertType=InsertType.NORMAL,
graphName="graph1",
CreateNodeIfNotExist=True
)
)
auto_insert_edge_result2.Print()
See documentation insertEdgesBatchAuto() for details.
The auto_insert_edge_result1 in the above example will throw error since it tries to insert edges whose start-node and end-node (student 'S001' and 'S002') are not yet in the graph.
The auto_insert_edge_result2 expresses a smooth insert operation, because it specifies CreateNodeIfNotExist as True in the InsertConfig
, which allows nodes of student 'S001' and 'S002' to be inserted automatically by the Ultipa server.
Interfaces
insertNodesBatchAuto()
andinsertEdgesBatchAuto()
both require all the custom properties of a metadata to be built in the metadata list. If any custom property is missing, i.e., a student node missing name or age or both, error will throw.
By Schema
Another two interfaces allow inserting metadata whose list is built with only part of custom properties defined by their schemas:
insertNodesBatchBySchema()
insertEdgesBatchBySchema()
The price of doing so is to specify in an instance of Schema
what properties are included in the metadata list, and pass that into the interfaces. And obviously, this requires all the metadata in the list to be of the same schema, and all the custom properties declared in the Schema
instance should be included when building the metadata list.
The following code inserts student 'S002' and 'S003' with only property name provided:
schema = Schema(
name="student",
dbType=DBType.DBNODE,
properties=[Property("name", ULTIPA.PropertyType.PROPERTY_STRING)]
)
studentList = [
EntityRow(id = "S001", values = {"name": "Pepe"}),
EntityRow(id = "S002", values = {"name": "Emma"})
]
by_schema_insert_node_result = connection.insertNodesBatchBySchema(
schema=schema,
rows=studentList,
config=InsertConfig(
insertType=InsertType.UPSERT,
graphName="graph1"
)
)
by_schema_insert_node_result.Print()
See documentation insertNodesBatchBySchema() and insertEdgesBatchBySchema() for details.
The
InsertConfig
in the above example specifies the insert operation to be done in 'UPSERT' mode, this is because nodes of student 'S001' and 'S002' are already inserted by the system in the previous example when inserting edges.
Query
All queries through Ultipa Python SDK can be executed by passing the UQL string into uql()
. The query results can be retrieved by calling methods get()
or alias()
of UltipaResponse
returned by uql()
.
See documentation UltipaResponse for details.
As will be demonstrated in the following code, to retrieve a data item from the returned UltipaResponse
, pass the index of data item into get()
, or pass the alias of data item into alias()
:
ultipaResponse = connection.uql("with 2023 as number with 'abc' as string with [1,2,3] as list return number, string, list")
print("The first data item is: ", ultipaResponse.get(0).toJSON())
print("Data item 'list' is: ", ultipaResponse.alias("list").toJSON())
The first data item is: {"alias": "number", "data": {"name": "number", "type": 4, "type_desc": "ATTR", "values": [2023]}, "type": "ATTR"}
Data item 'list' is: {"alias": "list", "data": {"name": "list", "type": 4, "type_desc": "ATTR", "values": [[1, 2, 3]]}, "type": "ATTR"}
Methods get()
and alias()
will return class DataItem
that has a bunch of methods, which further parse the data item into different data structs.
See documentation DataItem for details.
Data structs returned by different methods of DataItem
correspond to data types NODE, EDGE, PATH, TABLE and ATTR defined by Ultipa.
Node
Use method asNodes()
of DataItem
to convert a data item to List[Node
].
The following code queries all nodes in graph1 and output those nodes:
nodeResponse = connection.uql(
uql="find().nodes() as nodes return nodes{*}",
requestConfig=RequestConfig("graph1")
)
allNodes = nodeResponse.alias("nodes").asNodes()
firstNode = nodeResponse.alias("nodes").asFirstNodes()
for node in allNodes:
print(node.toDict())
print(firstNode.get("name"))
{'id':'S003', 'schema':'student', 'values':{'name': 'Jason', 'age': 27}, 'uuid': 1}
{'id':'P001', 'schema':'professor', 'values':{'name': 'Peter', 'age': 41}, 'uuid': 2}
{'id':'S001', 'schema':'student', 'values':{'name': 'Pepe'}, 'uuid': 3}
{'id':'S002', 'schema':'student', 'values':{'name': 'Emma'}, 'uuid': 4}
Jason
See documentation asNodes() and Node for details.
Edge
Use method asEdges()
of DataItem
to convert a data item to List[Edge
].
The following code queries all edges in graph1 and output these edges:
edgeResponse = connection.uql(
uql="find().edges() as edges return edges{*}",
requestConfig=RequestConfig("graph1")
)
allEdges = edgeResponse.alias("edges").asEdges()
firstEdge = edgeResponse.alias("edges").asFirstEdges()
for edge in allEdges:
print(edge.toDict())
print(firstEdge.get("year"))
{'from_id':'S001', 'from_uuid':3, 'to_id':'P001', 'to_uuid':2, 'schema':'assist', 'values':{'year': 2022}, 'uuid': 1}
{'from_id':'P001', 'from_uuid':2, 'to_id':'S002', 'to_uuid':4, 'schema':'mentor', 'values':{'year': 2021}, 'uuid': 2}
{'from_id':'P001', 'from_uuid':2, 'to_id':'S003', 'to_uuid':1, 'schema':'mentor', 'values':{'year': 2023}, 'uuid': 3}
2022
See documentation asEdges() and Edge for details.
Path
Use method asPaths()
of DataItem
to convert a data item to List[Path
].
The following code queries all one-step paths with a right-pointing edge in graph1 and print their initial nodes:
pathResponse = connection.uql(
uql="n().re().n() as paths return paths{*}",
requestConfig=RequestConfig("graph1")
)
allPaths = pathResponse.alias("paths").asPaths()
for path in allPaths:
print(path.getNodes()[0].toDict())
{'id':'P001', 'schema':'professor', 'values':{'name': 'Peter', 'age': 41}, 'uuid': 2}
{'id':'P001', 'schema':'professor', 'values':{'name': 'Peter', 'age': 41}, 'uuid': 2}
{'id':'S003', 'schema':'student', 'values':{'name': 'Jason', 'age': 27}, 'uuid': 1}
See documentation asPaths() and Path for details.
Table
Use method asTable()
of DataItem
to convert a data item to Table
.
The following code queries one-step paths of mentoring relations in graph1, assembles their initial-node and terminal-node as a table and output the rows in the table:
tableResponse = connection.uql(
uql="n(as n1).re({@mentor}).n(as n2) return table(n1.name, 'mentor', n2.name) as table",
requestConfig=RequestConfig("graph1")
)
allRows = tableResponse.alias("table").asTable().getRows()
for row in allRows:
print(row)
['Peter', 'mentor', 'Emma']
['Peter', 'mentor', 'Jason']
See documentation asTable() and Table for details.
Attr
Data type ATTR returned by Ultipa server contains values of string, number, list and point defined by Ultipa.
Use method asAttr()
of DataItem
to convert a data item to Attr
.
The following code queries all nodes in graph1, group these nodes by their schemas and collect name of nodes of a same group in an array:
attrResponse = connection.uql(
uql="find().nodes() as nodes group by nodes.@ return collect(nodes.name) as collection",
requestConfig=RequestConfig("graph1")
)
wholeAttr = attrResponse.alias("collection").asAttr()
for attr in wholeAttr:
print(attr)
['Json', 'Pepe', 'Emma']
['Peter']
See documentation asAttr() and Attr for details.
Update Metadata
Ultipa Python SDK currently doesn't provide interface to update metadata. To do so one should call uql()
where a UQL string of update() command is passed in.
Delete Metadata
Ultipa Python SDK currently doesn't provide interface to delete metadata. To do so one should call uql()
where a UQL string of delete() command is passed in.
Export Metadata
To export metadata of a schema, specify the DB type, number of metadata, schema name and the list of properties to export using Export
and pass into export()
.
The following code exports 100 student nodes with property name from graph1:
exportResponse = connection.export(
ULTIPA_REQUEST.Export(
type=DBType.DBNODE,
limit=100,
schema="student",
properties=["name"]
),
RequestConfig("graph1")
)
for student in exportResponse.data:
print(student.toDict())
{'id':'S003', 'schema':'student', 'values':{'name': 'Jason'}, 'uuid': 1}
{'id':'S001', 'schema':'student', 'values':{'name': 'Pepe'}, 'uuid': 3}
{'id':'S002', 'schema':'student', 'values':{'name': 'Emma'}, 'uuid': 4}
See documentation Export and export() for details.
Other Operations on GraphSet
Show GraphSet
To show graphset in the connected Ultipa server, use one of the following approaches:
- Via interface (one graphset): pass the name of graphset into
getGraph()
- Via interface (all graphsets): call
showGraph()
- Via UQL (one or all graphsets): pass the UQL string of showing graphset into
uql()
The following code shows graphset graph1 via interface:
graph = connection.getGraph(graphName="graph1").data
print(graph)
The following code shows all graphsets via interface:
graphs = connection.showGraph().data
for graph in graphs:
print(graph)
See documentation getGraph() and showGraph() for details.
Alter GraphSet
The name and/or description of a graphset can be altered using one of the following approaches:
- Via interface: pass the name of the graphset to be altered as well as the new name and/or new description into
alterGraph()
- Via UQL: pass the UQL string of altering graphset into
uql()
The following code alters graphset graph2 with a new name via interface:
connection.alterGraph(
oldGraphName="graph2",
newGraphName="new_graph",
newDescription="graphset altered via interface"
)
See documentation alterGraph() for details.
Drop GraphSet
To drop graphset from the connected Ultipa server, use one of the following approaches:
- Via interface (one graphset): pass the name of graphset into
dropGraph()
- Via UQL (multiple graphsets): pass the UQL string of dropping graphset into
uql()
The following code drops graphset graph4 via interface:
connection.dropGraph(graphName="graph4")
See documentation dropGraph() for details.
Other Operations on Graph Model
Show Schema
To show schema in the connected graphset, use one of the following approaches:
- Via interface (one schema): pass the DB type and name of schema into
showSchema()
- Via interface (all node schemas or all edge schemas): pass the DB type of schema into
showSchema()
- Via interface (all schemas): call
showSchema()
- Via UQL (one or all node schemas or all edge schemas or all schemas): pass the UQL string of showing schema into
uql()
The following code shows node schema student in graph1 via interface:
nodeSchema = connection.showSchema(
dbType=DBType.DBNODE,
schemaName="student",
requestConfig=RequestConfig("graph1")
).get(0).asSchemas()[0]
print(nodeSchema)
The following code shows all node schemas in graph1 via interface:
nodeSchemas = connection.showSchema(
dbType=DBType.DBNODE,
requestConfig=RequestConfig("graph1")
).get(0).asSchemas()
for schema in nodeSchemas:
print(schema)
The following code shows all schemas in graph1 via interface:
allSchemas = connection.showSchema(requestConfig=RequestConfig("graph1"))
nodeSchemas = allSchemas.alias("_nodeSchema").asSchemas()
edgeSchemas = allSchemas.alias("_edgeSchema").asSchemas()
for schema in nodeSchemas:
print(schema)
for schema in edgeSchemas:
print(schema)
See documentation showSchema() for details.
Alter Schema
The name and/or description of a schema can be altered using one of the following approaches:
- Via interface: pass the DB type and name of the schema to be altered as well as the new name and/or new description into
alterSchema()
- Via UQL: pass the UQL string of altering schema into
uql()
The following code alters edge schema mentor in graph1 via interface:
connection.alterSchema(
dbType=DBType.DBEDGE,
schemaName="mentor",
newSchemaName="instruct",
description="schema altered via interface",
requestConfig=RequestConfig("graph1")
)
See documentation alterSchema() for details.
Drop Schema
To drop schema from the connected Ultipa server, use one of the following approaches:
- Via interface (one schema): pass the DB type and name of schema into
dropSchema()
- Via UQL (multiple schemas): pass the UQL string of dropping schema into
uql()
The following code drops edge schema assist from graph1 via interface:
connection.dropSchema(
dbType=DBType.DBEDGE,
schemaName="assist",
requestConfig=RequestConfig("graph1")
)
See documentation dropSchema() for details.
Show Property
To show properties in the connected graphset, use one of the following approaches:
- Via interface (properties of one schema): pass the DB type and name of schema into
getProperty()
- Via interface (properties of all node schemas or all edge schemas): pass the DB type of schema into
getProperty()
- Via interface (properties of all schemas): call
showProperty()
- Via UQL (properties of one or all node schemas or all edge schemas or all schemas): pass the UQL string of showing property into
uql()
The following code shows properties of node schema student in graph1 via interface:
propsOfANodeSchema = connection.getProperty(
dbType=DBType.DBNODE,
schema="student",
requestConfig=RequestConfig("graph1")
).data[0].data
for property in propsOfANodeSchema:
print(property)
The following code shows properties of all node schemas in graph1 via interface:
propsOfAllNodeSchemas = connection.getProperty(
dbType=DBType.DBNODE,
requestConfig=RequestConfig("graph1")
).data[0].data
for property in propsOfAllNodeSchemas:
print(property)
The following code shows all schemas in graph1 via interface:
propsOfAllSchemas = connection.showProperty(requestConfig = RequestConfig("graph1")).data[0].data
for property in propsOfAllSchemas:
print(property)
See documentation getProperty() and showProperty() for details.
Alter Property
The name and/or description of a property can be altered using one of the following approaches:
- Via interface: pass the DB type, schema and name of property to be altered as well as the new name and/or new description into
alterProperty()
- Via UQL: pass the UQL string of altering property into
uql()
The following code alters node property name of schema professor in graph1 via interface:
connection.alterProperty(
dbType=DBType.DBNODE,
schema="professor",
property="name",
newProperty="firstname",
description="property altered via interface",
requestConfig=RequestConfig("graph1")
)
See documentation alterProperty() for details.
Drop Property
To drop property from the connected Ultipa server, use one of the following approaches:
- Via interface (one property): pass the DB type, schema and name of property into
dropProperty()
- Via UQL (multiple properties): pass the UQL string of dropping property into
uql()
The following code drops node property age of schema student from graph1 via interface:
connection.dropProperty(
dbType=DBType.DBNODE,
schema="student",
property="age",
requestConfig=RequestConfig("graph1")
)
See documentation dropProperty() for details.
Operations on Algorithm
Show Algorithm
Call showAlgo()
to show all the algorithms installed in the connected Ultipa server:
for algo in connection.showAlgo().data:
print(algo)
See documentation showAlgo() for details.
Install Algorithm
To install an algorithm to the connected Ultipa server, pass the directory of the .so
and .yml
files into installAlgo()
.
The following code installs the LPA algorithm whose files are placed in the current Python project directory:
connection.installAlgo(
algoFilePath="./libplugin_lpa.so",
algoInfoFilePath="./lpa.yml"
)
See documentation installAlgo() for details.
Uninstall Algorithm
To uninstall an algorithm from the connected Ultipa server, pass the name of the algorithm into uninstallAlgo()
.
The following code uninstalls the LPA algorithm from the connect Ultipa server:
connection.uninstallAlgo(algoName="lpa")
See documentation uninstallAlgo() for details.
Download Task File
If an algorithm is executed as 'writeback to file' against a specific graphset, the execution result can be downloaded from the algorithm task. Specify the file name, the task ID and the directory where to save the file using Download
and pass into download()
.
The following code downloads file 'degree_test' from task '134' that run against graphset graph1 and save it to local directory './test.csv':
form ultipa.types.types_request import Download
connection.download(
request=Download(
fileName="degree_test",
taskId="134",
savePath="./test.csv"
),
requestConfig=RequestConfig("graph1")
)
The
RequestConfig
must be used to specify the graphset, if not the one being connected, against which the task was executed.
See documentation Download and download() for details.
Property Type Reference
Ultipa | Python |
---|---|
string | string |
text | string |
float | float |
double | float |
int32 | int |
uint32 | int |
int64 | int |
uint64 | int |
datetime | string |
timestamp | string, int |