概述
本文档介绍 UModel 中的高级图查询功能,主要涵盖 Cypher 查询语言的使用,包括基础查询、多级跳跃、聚合统计、路径模式查找等高级特性,以及数据完整性处理和性能优化建议。
应用案例
当前应用案例相关素材,请参考:umodel.zip
Cypher查询详解
基础语法结构
Cypher采用声明式查询语言,遵循SQL类似的三段式结构:
.topo | graph-call cypher(`
MATCH <图查询路径>
WHERE <筛选条件>
RETURN <返回内容>
`)
基础三段式查询
单节点查询
-- 查询特定类型的所有节点
.topo | graph-call cypher(`
MATCH (n {__entity_type__:"apm.service"})
WHERE n.__domain__ STARTS WITH 'a' AND n.__entity_type__ = "apm.service"
RETURN n
`)
相比 graph-match 的优势:
支持 WHERE 子句进行复杂筛选。
MATCH 可以只包含节点,无需指定关系。
支持更多的属性查询(
__entity_type__
、__domain__
等)。
关系查询
-- 查询服务间调用关系
.topo | graph-call cypher(`
MATCH (src:``apm@apm.service``)-[e:calls]->(dest:``apm@apm.service``)
WHERE src.cluster = 'production' AND dest.cluster = 'production'
RETURN src.service_name, dest.service_name, e.__type__
`)
多级跳查询
基础多级跳语法
-- 查找2-3跳的调用链路
.topo | graph-call cypher(`
MATCH (src {__entity_type__:"acs.service"})-[e:calls*2..3]->(dest)
WHERE dest.__domain__ = 'acs'
RETURN src, dest, dest.__entity_type__
`)
重要说明:
多级跳规则是左闭右开:
*2..3
表示只查询2跳。*1..3
表示1跳或2跳,不包括3跳。单个数字
*3
表示恰好3跳。
多级跳应用场景
连通性分析:
-- 查找服务间的可达路径
.topo | graph-call cypher(`
MATCH (startNode:``apm@apm.service`` {service_name: 'gateway'})
-[path:calls*1..4]->
(endNode:``apm@apm.service`` {service_name: 'database'})
RETURN startNode.service_name, length(path) as hop_count, endNode.service_name
`)
影响链分析:
-- 分析故障传播路径
.topo | graph-call cypher(`
MATCH (failed:``apm@apm.service`` {status: 'error'})
-[impact:depends_on*1..3]->
(affected)
WHERE affected.__entity_type__ = 'apm.service'
RETURN failed.service_name,
length(impact) as impact_distance,
affected.service_name
ORDER BY impact_distance ASC
`)
节点聚合统计
基础聚合查询
-- 统计不同域的服务数量
.topo | graph-call cypher(`
MATCH (src {__entity_type__:"apm.service"})-[e:calls*2..3]->(dest)
WHERE dest.__domain__ = 'apm'
RETURN src, count(src) as connection_count
`)
适用场景:
连通分量分析:识别图中的连通子图。
中心度计算:找出网络中的关键节点。
集群检测:发现紧密连接的节点群组。
路径模式查找
复杂路径模式
-- 查找特定的拓扑模式
.topo | graph-call cypher(`
MATCH (src:``acs@acs.vpc.vswitch``)-[e1]->(n1)<-[e2]-(n2)-[e3]->(n3)
WHERE NOT (src = n2 AND e1.__type__ = e2.__type__)
AND n1.__entity_type__ <> n3.__entity_type__
AND NOT (src)<-[e1:``calls``]-(n1)
RETURN src, e1.__type__, n1, e2.__type__, n2, e3.__type__, n3
`)
适用场景:
安全审计:发现异常的网络连接模式。
合规检查:验证网络架构的合规性。
模式检测:识别特定的系统拓扑结构。
完整Cypher功能:支持自定义节点属性
自由属性查找
基于实体自定义属性查询
-- 使用实体的自定义属性进行查询
.topo | graph-call cypher(`
MATCH (n:``acs@acs.alb.listener`` {ListenerId: 'lsn-rxp574lk5vu3gos29g'})-[e]->(d)
WHERE d.vSwitchId CONTAINS 'vsw-bp1gvyids4uwo20crmp15'
AND d.user_id IN ['1654218965343050', '2']
AND d.dnsName ENDS WITH '.com'
RETURN n, e, d
`)
属性条件组合
-- 复杂的属性条件查询
.topo | graph-call cypher(`
MATCH (instance:``acs@acs.ecs.instance``)
WHERE instance.instance_type STARTS WITH 'ecs.c6'
AND instance.cpu_cores >= 4
AND instance.memory_gb >= 8
AND instance.status = 'Running'
AND instance.create_time > '2024-01-01'
RETURN
instance.instance_id,
instance.instance_type,
instance.cpu_cores,
instance.memory_gb,
instance.availability_zone
ORDER BY instance.cpu_cores DESC, instance.memory_gb DESC
`)
多级路径输出
路径信息返回
-- 返回多级跳的完整路径信息
.topo | graph-call cypher(`
MATCH (n:``acs@acs.alb.listener``)-[e:``calls``*2..3]-()
RETURN e
`)
路径结果格式:
返回路径中所有边的数组。
每个边包含完整的起止节点和属性信息。
支持路径长度和路径权重计算。
真实业务场景应用
1. 细粒度链路控制的连通性查找
跨网络层级的连接分析
-- 查找ECS实例到负载均衡器的连接路径
.topo | graph-call cypher(`
MATCH (start_node:``acs@acs.ecs.instance``)
-[e*2..3]-
(mid_node {ListenerName: 'entity-test-listener-zuozhi'})
-[e2*1..2]-
(end_node:``acs@acs.alb.loadbalancer``)
WHERE start_node.__entity_id__ <> mid_node.__entity_id__
AND start_node.__entity_type__ <> mid_node.__entity_type__
RETURN
start_node.instance_name,
e,
mid_node.__entity_type__,
e2,
end_node.instance_name
`)
服务网格连接分析
-- 分析微服务网格中的流量路径
.topo | graph-call cypher(`
MATCH (client:``apm@apm.service``)
-[request:calls]->
(gateway:``apm@apm.gateway``)
-[route:routes_to]->
(service:``apm@apm.service``)
-[backend:calls]->
(database:``middleware@database``)
WHERE client.environment = 'production'
AND request.protocol = 'HTTP'
AND route.load_balancer_type = 'round_robin'
RETURN
client.service_name,
gateway.gateway_name,
service.service_name,
database.database_name,
request.request_count,
backend.connection_pool_size
`)
2. 拓扑图构建
等价的getNeighborNodes查询
-- 传统方式
.topo | graph-call getNeighborNodes(
'sequence', 5,
[(:"acs@acs.alb.listener" {__entity_id__: '0b04e22d024b31a4cb880c0b2c652638'})]
)
-- Cypher等价写法
.topo | graph-call cypher(`
MATCH (n:``acs@acs.alb.listener`` {__entity_id__: '0b04e22d024b31a4cb880c0b2c652638'})
-[e1*1..6]->(),
(n:``acs@acs.alb.listener`` {__entity_id__: '0b04e22d024b31a4cb880c0b2c652638'})
<-[e2*1..6]-()
RETURN n, e1, e2
`)
3. 故障诊断和影响分析
级联故障分析
-- 分析服务故障的级联影响
.topo | graph-call cypher(`
MATCH (failed_service:``apm@apm.service`` {status: 'error'})
MATCH cascade_path = (failed_service)-[impact:depends_on*1..4]->(affected_service)
WHERE affected_service.__entity_type__ = 'apm.service'
RETURN
failed_service.service_name as root_cause,
length(cascade_path) as impact_depth,
affected_service.service_name as affected_service,
affected_service.criticality_level,
impact as dependency_chain
ORDER BY impact_depth ASC, affected_service.criticality_level DESC
`)
数据完整性和故障排查
数据缺失场景分析
UModel | Entity | Topo | 查询表现 |
正常 | 正常 | 正常 | 正常情况,所有查询都可用。 |
正常 | 正常 | 缺失 | 无法进行图查询。 |
正常 | 缺失 | 正常 | 关系正常,但节点信息为空。 |
正常 | 缺失 | 缺失 | 完全无法查询,虽有Schema但无数据。 |
缺失 | 正常 | 正常 | 无法查询,纯拓扑模式可正常工作。 |
缺失 | 正常 | 缺失 | 完全无法查询。 |
缺失 | 缺失 | 正常 | 无法查询,pure-topo可正常工作。 |
缺失 | 缺失 | 缺失 | 完全无法查询。 |
pure-topo模式
当Entity数据不完整时,可以使用pure-topo模式,仅依赖关系数据进行查询:
-- 标准模式(需要完整数据)
.topo | graph-call cypher(`
MATCH (n:``acs@acs.alb.listener`` {ListenerId: 'lsn-123'})-[e]->(d)
WHERE d.vSwitchId CONTAINS 'vsw-456'
RETURN n, e, d
`)
-- pure-topo模式(仅依赖关系数据)
.topo | graph-call cypher(`
MATCH (n:``acs@acs.alb.listener``)-[e]->(d)
RETURN n, e, d
`, 'pure-topo')
pure-topo模式特点:
优势:不依赖Entity数据,查询速度更快。
限制:无法使用实体的自定义属性进行筛选。
适用:拓扑结构分析、关系验证等场景。
数据质量检查
检查数据完整性
-- 检查实体和关系的数据完整性
.topo | graph-call cypher(`
MATCH (n)-[e]->(m)
RETURN
count(DISTINCT n) as unique_nodes,
count(DISTINCT e) as unique_edges,
count(DISTINCT e.__type__) as edge_types,
collect(DISTINCT n.__entity_type__)[0..10] as node_types_sample
`)
识别悬挂关系
-- 查找指向不存在实体的关系
.let topoData = .topo | graph-call cypher(`
MATCH ()-[e]->()
RETURN e
`)
| extend startNodeId = json_extract_scalar(e, '$.startNodeId'), endNodeId = json_extract_scalar(e, '$.endNodeId'), relationType = json_extract_scalar(e, '$.type')
| project startNodeId, endNodeId, relationType;
--$topoData
.let entityData = .entity with(domain='*', type='*')
| project __entity_id__, __entity_type__, __domain__
| extend matchedId = concat(__domain__, '@', __entity_type__, ':', __entity_id__)
| join -kind='left' $topoData on matchedId = $topoData.endNodeId
| project matchedId, startNodeId, endNodeId, relationType
| extend status = COALESCE(startNodeId, '悬挂')
| where status = '悬挂';
$entityData
性能优化建议
1. 查询结构优化
合理使用索引
-- 优化前:全表扫描
.topo | graph-call cypher(`
MATCH (n) WHERE n.service_name = 'web-app'
RETURN n
`)
-- 优化后:使用标签索引
.topo | graph-call cypher(`
MATCH (n:``apm@apm.service`` {service_name: 'web-app'})
RETURN n
`)
早期条件过滤
-- 优化前:后期过滤
.topo | graph-call cypher(`
MATCH (start)-[*1..5]->(endNode)
WHERE start.environment = 'production' AND endNode.status = 'active'
RETURN start, endNode
`)
-- 优化后:早期过滤
.topo | graph-call cypher(`
MATCH (start {environment: 'production'})-[*1..5]->(endNode {status: 'active'})
RETURN start, endNode
`)
2. 结果集控制
分页和限制
-- 使用LIMIT控制结果数量
.topo | graph-call cypher(`
MATCH (service:``apm@apm.service``)-[calls:calls]->(target)
WHERE calls.request_count > 1000
RETURN service.service_name, target.service_name, calls.request_count
ORDER BY calls.request_count DESC
LIMIT 50
`)
结果采样
-- 对大结果集进行采样
.topo | graph-call cypher(`
MATCH (n:``apm@apm.service``)
RETURN n.service
LIMIT 100
`)
| extend seed = random()
| where seed < 0.1
3. 多级跳优化
控制跳跃深度
-- 避免过深的遍历
.topo | graph-call cypher(`
MATCH (start)-[path*1..3]->(endNode)
WHERE length(path) <= 2
RETURN path
`)
使用方向性优化
-- 利用关系方向减少搜索空间
.topo | graph-call cypher(`
MATCH (start)-[calls:calls*1..3]->(endNode) -- 明确方向
WHERE start.__entity_type__ = 'apm.service'
RETURN start, endNode
`)