Asset图数据库基于关系的查询 - 关系遍历
Asset图数据库基于关系的查询 - 关系遍历
前面我们提到,相比关系型数据库,Asset图数据库最大不同的特性就是关系是和实体一样的一等公民。因此,GEL不仅支持基于属性的查询,而且支持基于关系的查询。在构建基于关系的查询之前,我们先来理解一下资产主数据中的关系。
以火车机车收集器中的两个对象为例,如下所示。
[
{
"uri": "/locomotives/1",
"type": "Diesel-electric",
"model": "ES44AC",
"serial_no": "001",
"emission_tier": "0+",
"fleet": "/fleets/up-1",
"manufacturer": "/manufacturers/GE",
"engine": "/engines/v12-1",
"installedOn": "01/12/2005",
"dateIso": "2005-12-01T13:15:31Z",
"hqLatLng": {
"lat": 33.914605,
"lng": -117.253374
}
},
{
"uri": "/locomotives/2",
"type": "Diesel-electric",
"model": "SD70ACe",
"serial_no": "002",
"emission_tier": "0+",
"fleet": "/fleets/up-1",
"manufacturer": "/manufacturers/electro-motive-diesel",
"engine": "/engines/v16-2-1",
"hqLatLng": {
"lat": 47.655492,
"lng": -117.427025
}
}
]
我们可以看到火车机车对象/locomotives/1
属于车队/fleets/up-1
,拥有引擎/engines/v12-1
,制造商为/manufacturers/GE
,机车对象/locomotives/2
也有相类似的关系。根据这些信息,我们可以画出如下对象关系网络。
Asset数据库中的所有关系都是有方向的,跟随箭头的方向查询对象称之为向前遍历,跟箭头方向相反的查询对象称之为向后遍历。例如,在上图中,从火车机车locomotives到制造商manufactures是向前遍历。在上述JSON的描述中,制造商是火车机车对象的一个属性,所以,“制造商为”关系的方向是从火车机车到制造商。相同的道理,从车队fleets到火车机车locomotives就是向后遍历。多个对象可以指向同一个对象,这和我们在现实世界的直观认知是一致的。例如,机车1和机车2都属于同一个车队up-1。随着越来越多的对象和关系被添加进来,上述图形就会随之增长。
向前遍历运算符>
当我们理解了Asset数据库中对象间的关系,我们就可以开始构建基于关系的查询了。例如,类型为diesel-electric
的火车机车的制造商是哪家?向前遍历运算符>
代表对象间向前遍历查询,因此,上述问题的查询语句为/manufacturers?filter=type=Diesel-electric>manufacturer
。我们来详细解析一下这条GEL查询语句的内部逻辑,这样会帮助我们理解基于关系的查询。
步骤 | 逻辑 | 语法 | 返回对象 |
---|---|---|---|
第一步 | 查询所有类型为Diesel-electric 的对象 |
filter=type=Diesel-electric |
在图数据库中,所有的对象都是同等重要的,没有特定查询起点。因此,过滤子句是面向Asset数据库中的所有对象进行查询,返回所有匹配的对象,包括火车机车对象和其他对象 |
第二步 | 在上一步返回的对象中,向前遍历查询关系是制造商为manufacturer 所指向的对象 |
>manufacturer |
返回所有匹配的对象,包括制造商对象和其他由关系manufacturer 所指向的对象 |
第三步 | 在上一步返回的对象中,查询收集器为manufacturers 的对象 |
/manufacturers |
因为有了收集器的限定,所以,返回所有匹配的对象,一定是制造商的对象信息 |
注:上述查询语句中的
manufacturer
表示对象间的关系“制造商为”,而manufacturers
表示收集器名称是“制造商”。
那么,向前遍历的查询和前面讲到的通过筛选子句查找制造商信息有什么区别么?例如,/locomotives?filter=type=Diesel-electric&fields=manufacturer
也可以完成“类型为diesel-electric
的火车机车的制造商是哪家?”这种查询。但是,我们可以看到明显的区别,
- 通过使用向前遍历运算符,我们查询到的是制造商对象的具体信息,包括,制造商的名称,资质,等所有属性。
- 通过使用筛选子句,我们查询到的是火车机车对象中制造商的URI信息,而不是制造商对象的具体属性信息。
向后遍历运算符<
当我们理解了向前遍历运算符,那么理解向后遍历运算符就比较容易了。例如,服务于客户Union Pacific
的车队有哪些?在第四节的数据建模中,我们定义了车队服务于客户的关系。因此,我们要完成上述查询,就需要用到向后遍历运算符<
,从车队到客户的关系中,通过客户反向查询车队的信息。那么,这个问题的查询语句为/fleets?filter=name=Union Pacific<customer
。我们还是详细解析一下这条向后遍历的GEL查询语句。
步骤 | 逻辑 | 语法 | 返回对象 |
---|---|---|---|
第一步 | 查询所有名称为Union Pacific 的对象 |
filter=name=Union Pacific |
返回所有匹配的对象,包括客户对象和其他对象 |
第二步 | 在上一步返回的对象中,向后遍历查询含有关系是服务于customer 的对象 |
<customer |
返回所有匹配的对象,包括车队对象和其他含有关系是customer 的对象 |
第三步 | 在上一步返回的对象中,查询收集器为fleets 的对象 |
/fleets |
因为有了收集器的限定,所以,返回所有匹配的对象,一定是车队的对象信息 |
当然,向前遍历和向后遍历运算符也可以一起使用。例如,生产引擎马力为4300的制造商还生产了哪些火车机车?GEL的查询语句为/locomotives?filter=horsepower=4300>manufacturer<manufacturer
。我们还可以设计其他更为复杂的遍历查询,来满足具体的业务需要。
作者:谢品,上海创新坊首席架构师,GE数字集团
专注于工业互联网,云计算,大数据,高性能分布式存储领域,对Cloud Foundry和传统应用向云端迁移,特别是向Predix迁移有丰富的经验,曾供职于VMware,EMC,Autodesk等知名软件公司云计算部门。