环境需求
- 启动最新版的 Ultipa V4.3 服务器集群,如 192.168.1.85:60061,192.168.1.86:60061,192.168.1.87:60061
- 安装最新版 Ultipa Python SDK V4.3,参阅 Installation
创建连接
连接到 Ultipa 服务器时,使用 UltipaConfig
实例化服务器的连接信息,并传入 Connection.NewConnection()
。
当 UltipaConfig
的配置项 defaultGraph 没有填写时,将使用默认图集 default:
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)
参阅 API 文档 UltipaConfig,Connection。
一个连接创建后,对其 UltipaConfig
实例所做的修改将会自动更新该连接。
以下代码将已创建好的连接所使用的图集切换至 amz:
ultipaConfig.defaultGraph = "amz"
使用 LoggerConfig
实例化 logger 信息,并更新 UltipaConfig
实例。以下代码通过设置 logger 将连接的各项活动输出至控制台:
from ultipa.utils.logger import LoggerConfig
loggerConfig = LoggerConfig(name="myLog", isStream=True)
ultipaConfig.uqlLoggerConfig = loggerConfig
connection.test().Print()
对 LoggerConfig
实例所做的修改同样会自动更新其 UltipaConfig
实例,进而自动更新其所对应的连接。以下代码通过修改 logger 将连接的各项活动写入文件:
loggerConfig.filename = "myLogFile"
loggerConfig.isWriteToFile = True
参阅 API 文档 LoggerConfig。
创建图集
通过以下方式在已连接的 Ultipa 服务器中创建图集:
- 接口(一个图集):使用
Graph
实例化图集的名称和描述,并传入createGraph()
- UQL(多个图集): 将创建图集的 UQL 语句传入
uql()
以下代码通过接口创建图集 graph1:
from ultipa import Graph
connection.createGraph(graph=Graph(
name="graph1",
description="graphset created via interface"
))
以下代码通过发送 UQL 创建图集 graph2,graph3,graph4:
connection.uql("create().graph('graph2','graphset created via uql').graph('graph3','graphset created via uql').graph('graph4','graphset created via uql')")
参阅 API 文档 Graph,createGraph(),uql()。
关于图集的查看、修改、删除操作在后面进行介绍。
定义图模型
图模型是指元数据的 schema 及其属性的定义。
创建 Schema
点schema default 和边schema default 是图集中的默认schema。通过以下方式在已连接的 Ultipa 图集中创建 schema:
- 接口(一个 schema):使用
Schema
实例化 schema 的名称、DB类型和描述,并传入createSchema()
- UQL(多个 schema):将创建 schema 的 UQL 语句传入
uql()
以下代码通过接口在当前连接的图集中创建点schema student:
from ultipa import Schema
from ultipa import DBType
connection.createSchema(schema=Schema(
name="student",
dbType=DBType.DBNODE,
description="in the connected graphset"
))
参阅 API 文档 Schema,createSchema(),DBType。
如果要在其他图集中创建 schema,可以通过 UltipaConfig
将当前连接切换至目标图集后再创建,或者在调用 createSchema()
时使用 RequestConfig
声明目标图集。
以下代码通过接口在图集 graph1 中创建点schema student:
from ultipa import RequestConfig
connection.createSchema(
schema=Schema(
name="student",
dbType=DBType.DBNODE,
description="in graph1"
),
requestConfig=RequestConfig(graphName="graph1")
)
参阅 API 文档 RequestConfig。
RequestConfig
只规定某一次非插入操作所针对的图集,并非改变当前连接所使用的图集。
以下代码通过发送 UQL 在图集 graph1 中创建点schema professor,边schema mentor、assist:
connection.uql(
uql="create().node_schema('professor').edge_schema('mentor').edge_schema('assist')",
requestConfig=RequestConfig(graphName="graph1")
)
关于 schema 的查看、修改、删除操作在后面进行介绍。
创建属性
通过以下方式在已连接的 Ultipa 图集的某 schema 中创建自定义属性:
- 接口(一个属性):将属性的 DB 类型、schema 名称、和属性的具体信息(使用
Property
进行实例化)传入createProperty()
- UQL(多个属性):将创建属性的 UQL 语句传入
uql()
以下代码通过接口创建为图集 graph1 的点schema student 创建属性 name:
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")
)
参阅 API 文档 Property,createProperty(),PropertyTypeStr。
参照以下 scheam 及属性结构:
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 |
以下代码通过发送 UQL 为图集 graph1 创建以上这些属性:
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")
)
关于属性的查看、修改、删除操作在后面进行介绍。
插入元数据
元数据是指图集中的点、边。插入前需先构造好以 EntityRow
为元素的元数据列表。
参阅 API 文档 EntityRow。
Auto
以下两个接口可以一次插入不同 schema 的元数据:
insertNodesBatchAuto()
insertEdgesBatchAuto()
使用以上两个接口时,要求所构造的元数据列表中每一个元数据均携带其所属的 schema 信息。
参阅 API 文档 EntityRow。
以下代码通过接口向图集 graph1 中插入学生点 'S003' 和教授点 'P001':
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()
参阅 API 文档 insertNodesBatchAuto(),InsertConfig,InsertType。
InsertConfig
规定某一次插入操作的插入类型(insert/upsert/overwrite)和连接信息(如目标图集等)。与RequestConfig
类似,它也不改变当前连接的各项配置。
以下代码通过接口创建向图集 graph1 的schema mentor 和 assist 中插入一列边:
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()
参阅 API 文档 insertEdgesBatchAuto()。
上面示例中的 auto_insert_edge_result1 会引发报错,原因是其所尝试插入的边的起点和终点(学生点 'S001' 和 'S002')在图集中不存在。
而 auto_insert_edge_result2 正常,因为其 InsertConfig
将 CreateNodeIfNotExist 设置为 True,表示允许不存在的学生点 'S001' 和 'S002' 被自动插入。
接口
insertNodesBatchAuto()
和insertEdgesBatchAuto()
均要求待插入的元数据的所有自定义属性被构建于列表中,否则将报错,例如学生点未携带属性 name 和/或 age 的情况。
By Schema
以下两个接口允许被插入的元数据仅携带其 schema 中包含的 一部分自定义属性:
insertNodesBatchBySchema()
insertEdgesBatchBySchema()
使用以上两个接口时,需要使用 Schema
实例化元数据所携带的属性信息,并传入接口。显然,此种设计要求被插入的元数据均属于同一个 schema,并且所构造的元数据列表必须包含所有被 Schema
实例声明的属性。
以下代码在插入学生点 'S002' 和 'S003' 时仅携带了属性 name:
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()
参阅 API 文档 insertNodesBatchBySchema(),insertEdgesBatchBySchema()。
以上示例中的
InsertConfig
和插入类型指定为 'UPSERT',这是由于学生点 'S001' 和 'S002' 已经在前一个插入边的示例中被系统自动插入了。
查询
Ultipa Python SDK 通过将查询的 UQL 语句传入 uql()
进行查询。uql()
的返回值为 UltipaResponse
类,该类提供方法 get()
和 alias()
来获取查询结果。
参阅 API 文档 UltipaResponse。
从返回的 UltipaResponse
类中获取某个数据项时,可以将该数据项的下标传入 get()
,或将该数据项的别名传入 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"}
方法 get()
和 alias()
的返回值为 DataItem
类,该类提供的不同方法将获得的数据项转为各种不同的数据结构。
参阅 API 文档 DataItem。
这些数据结构对应为 Ultipa 系统所定义的 5 种数据类型:NODE,EDGE,PATH,TABLE 和 ATTR。
Node
asNodes()
将一个数据项转为 List[Node
]。
以下代码查询了图集 graph1 中的所有点,并输出这些点:
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
Edge
asEdges()
将一个数据项转为 List[Edge
]。
以下代码查询了图集 graph1 中的所有边,并输出这些边:
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
Path
asPaths()
将一个数据项转为 List[Path
]。
以下代码查询了图集 graph1 中的所有含右向边的一步路径,并输出这些路径:
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}
Table
asTable()
将一个数据项转为 Table
类型。
以下代码查询了图集 graph1 中的所有含右向 @mentor 边的一步路径,将路径的起点、终点等信息组织为表格,并输出该表格中的每一行:
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']
Attr
Ultipa 的数据类型 ATTR 包括 Ultipa 所定义的 string,number,list 和 point 等类型的值。
asAttr()
将一个数据项转为 Attr
类型。
以下代码查询了图集 graph1 中的所有点,将这些点按 schema 分组后收集组内各点的 name 为数组,并输出这些数组:
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().values
for attr in wholeAttr:
print(attr)
['Json', 'Pepe', 'Emma']
['Peter']
更新元数据
Ultipa Python SDK 当前不提供更新元数据的接口。此功能可通过向 uql()
中传入相关 UQL 语句来实现。
删除元数据
Ultipa Python SDK 当前不提供删除元数据的接口。此功能可通过向 uql()
中传入相关 UQL 语句来实现。
导出元数据
导出元数据时,使用 Export
实例化元数据的 DB 类型,数量,schema 以及带导出的属性列表,并传入 export()
。
以下代码从 graph1 图集中导出了 100 个学生点的属性 name:
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}
图集的其他操作
显示图集
通过以下方式显示图集信息:
- 接口(一个图集):将图集名传入
getGraph()
- 接口(所有图集):调用
showGraph()
- UQL(一个或所有图集):将显示图集的 UQL 语句传入
uql()
以下代码通过接口显示图集 graph1 的信息:
graph = connection.getGraph(graphName="graph1").data
print(graph)
以下代码通过接口显示所有图集的信息:
graphs = connection.showGraph().data
for graph in graphs:
print(graph)
参阅 API 文档 getGraph(),showGraph()。
修改图集
通过以下方式修改图集的名称、描述:
- 接口:将图集名、新名称、新描述传入
alterGraph()
- UQL:将修改图集的 UQL 语句传入
uql()
以下代码通过接口修改图集 graph2 的名称:
connection.alterGraph(
oldGraphName="graph2",
newGraphName="new_graph",
newDescription="graphset altered via interface"
)
参阅 API 文档 alterGraph()。
删除图集
通过以下方式删除图集:
- 接口(一个图集):将图集名传入
dropGraph()
- UQL(多个图集):将删除图集的 UQL 语句传入
uql()
以下代码通过接口删除了图集 graph4:
connection.dropGraph(graphName="graph4")
参阅 API 文档 dropGraph()。
图模型的更多操作
显示 Schema
通过以下方式显示 schema 信息:
- 接口(一个 schema):将 schema 的 DB 类型和名称传入
showSchema()
- 接口(所有点schema、所有边schema):将 schema 的 DB 类型传入
showSchema()
- 接口(所有schema):调用
showSchema()
- UQL(一个或所有点 schema、一个或所有边schema):将显示 schema 的 UQL 语句传入
uql()
以下代码通过接口显示了图集 graph1 中的点schema student:
nodeSchema = connection.showSchema(
dbType=DBType.DBNODE,
schemaName="student",
requestConfig=RequestConfig("graph1")
).get(0).asSchemas()[0]
print(nodeSchema)
以下代码通过接口显示了图集 graph1 中的所有点schema:
nodeSchemas = connection.showSchema(
dbType=DBType.DBNODE,
requestConfig=RequestConfig("graph1")
).get(0).asSchemas()
for schema in nodeSchemas:
print(schema)
以下代码通过接口显示了图集 graph1 中的所有schema:
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)
参阅 API 文档 showSchema()。
修改 Schema
通过以下方式修改 schema 的名称、描述:
- 接口:将 schema 的 DB 类型,名称,新名称,新描述传入
alterSchema()
- UQL: 将修改 schema 的 UQL 语句传入
uql()
以下代码通过接口修改了图集 graph1 中的边schema mentor:
connection.alterSchema(
dbType=DBType.DBEDGE,
schemaName="mentor",
newSchemaName="instruct",
description="schema altered via interface",
requestConfig=RequestConfig("graph1")
)
参阅 API 文档 alterSchema()。
删除 Schema
通过以下方式删除 schema:
- 接口(一个 schema ):将 schema 的 DB 类型,名称传入
dropSchema()
- UQL(多个 schema ):将删除 schema 的 UQL 语句传入
uql()
以下代码通过接口删除了图集 graph1 中的边schema assist:
connection.dropSchema(
dbType=DBType.DBEDGE,
schemaName="assist",
requestConfig=RequestConfig("graph1")
)
参阅 API 文档 dropSchema()。
显示属性
通过以下方式显示属性信息:
- 接口(一个 schema 的属性):将 schema 的 DB 类型,名称传入
getProperty()
- 接口(所有点schema 或所有边 schema 的属性):将 schema 的 DB 类型传入
getProperty()
- 接口(所有 schema 的属性):调用
showProperty()
- UQL(一个或所有点 schema、一个或所有边schema 的属性):将显示属性的 UQL 语句传入
uql()
以下代码通过接口显示了图集 graph1 中的点schema student 的属性:
propsOfANodeSchema = connection.getProperty(
dbType=DBType.DBNODE,
schema="student",
requestConfig=RequestConfig("graph1")
).data[0].data
for property in propsOfANodeSchema:
print(property)
以下代码通过接口显示了图集 graph1 中所有点schema 的属性:
propsOfAllNodeSchemas = connection.getProperty(
dbType=DBType.DBNODE,
requestConfig=RequestConfig("graph1")
).data[0].data
for property in propsOfAllNodeSchemas:
print(property)
以下代码通过接口显示了图集 graph1 中的所有属性:
propsOfAllSchemas = connection.showProperty(requestConfig = RequestConfig("graph1")).data[0].data
for property in propsOfAllSchemas:
print(property)
参阅 API 文档 getProperty(),showProperty()。
修改属性
通过以下方式修改属性的名称、描述:
- 接口:将属性的 DB 类型,schema 名称,属性名,新名称,新描述传入
alterProperty()
- UQL:将修改属性的 UQL 语句传入
uql()
以下代码通过接口修改了图集 graph1 中点schema professor 的属性 name:
connection.alterProperty(
dbType=DBType.DBNODE,
schema="professor",
property="name",
newProperty="firstname",
description="property altered via interface",
requestConfig=RequestConfig("graph1")
)
参阅 API 文档 alterProperty()。
删除属性
通过以下方式删除属性:
- 接口(一个属性):将属性的 DB 类型,schema 名称,属性名传入
dropProperty()
- UQL(多个属性):将删除属性的 UQL 语句传入
uql()
以下代码通过接口删除了图集 graph1 中点schema professor 的属性 age:
connection.dropProperty(
dbType=DBType.DBNODE,
schema="student",
property="age",
requestConfig=RequestConfig("graph1")
)
参阅 API 文档 dropProperty()。
算法的相关操作
显示算法
调用 showAlgo()
显示当前 Ultipa 服务器中已安装的所有算法:
for algo in connection.showAlgo().data:
print(algo)
参阅 API 文档 showAlgo()。
安装算法
安装算法时,将算法的 .so
文件和 .yml
文件的路径传入 installAlgo()
。
以下代码安装了 LPA 算法,相关文件位于当前 Python 项目路径下:
connection.installAlgo(
algoFilePath="./libplugin_lpa.so",
algoInfoFilePath="./lpa.yml"
)
参阅 API 文档 installAlgo()。
卸载算法
安装算法时,将算法名传入 uninstallAlgo()
。
以下算法从当前 Ultipa 服务器中卸载了 LPA 算法:
connection.uninstallAlgo(algoName="lpa")
参阅 API 文档 uninstallAlgo()。
下载算法任务文件
当一个算法在某图集中以 'writeback to file' 的方式执行后,算法的执行结果可以从对应的算法任务中下载。此时使用 Download
实例化算法任务中的文件名,任务 ID 以及下载路径,并传入 download()
。
以下代码从图集 graph1 的任务 '134' 中下载文件 'degree_test' 值本地路径 './test.csv':
form ultipa.types.types_request import Download
connection.download(
request=Download(
fileName="degree_test",
taskId="134",
savePath="./test.csv"
),
requestConfig=RequestConfig("graph1")
)
从任务中下载文件时,如果该任务不是针对当前所连图集执行的,则需使用
RequestConfig
指明该图集。
参阅 API 文档 Download,download()。
属性对照表
Ultipa | Python |
---|---|
string | string |
text | string |
float | float |
double | float |
int32 | int |
uint32 | int |
int64 | int |
uint64 | int |
datetime | string |
timestamp | string 或 int |