结合"主机(Host)"和"进程(Process)"的业务场景,我们可以通过以下步骤统计主机之间的间接访问关系(基于进程间的访问):
一、明确数据模型
首先定义节点和关系的结构(便于理解查询逻辑):
-
节点:
:Host(主机):属性host_id(唯一标识,如主机IP或名称)。:Process(进程):属性process_id(唯一标识,如进程PID)。
-
关系:
:RUNS(主机运行进程):(Host)-[:RUNS]->(Process)(表示某主机上运行的进程)。:CALLS(进程访问进程):(Process)-[:CALLS]->(Process)(表示进程间的访问关系)。
二、核心逻辑:主机间访问关系的形成
当 主机A的进程P1访问主机B的进程P2 时,会形成一条路径:
(HostA)-[:RUNS]->(P1)-[:CALLS]->(P2)<-[:RUNS]-(HostB)
通过匹配这条路径,即可提取出间接相关的主机对 (HostA, HostB),进而统计它们之间的访问关系。
三、具体统计需求及Cypher实现
场景1:统计"主机对之间是否存在访问关系"(去重)
即只要存在一次跨主机的进程访问,就记录这对主机的访问关系(不统计次数)。
cypher
// 匹配跨主机的进程访问路径
MATCH
(h1:Host)-[:RUNS]->(p1:Process)-[:CALLS]->(p2:Process)<-[:RUNS]-(h2:Host)
WHERE
h1.host_id <> h2.host_id // 排除同一主机内的进程访问
// 提取主机对(保留方向:h1访问h2)
WITH
h1.host_id AS source_host,
h2.host_id AS target_host
// 去重,仅保留存在访问关系的主机对
RETURN
source_host,
target_host,
'has_access' AS relationship_type
ORDER BY source_host, target_host
结果示例:
| source_host | target_host | relationship_type |
|---|---|---|
| 192.168.1.1 | 192.168.1.2 | has_access |
| 192.168.1.1 | 192.168.1.3 | has_access |
场景2:统计"主机对之间的访问次数"(按进程访问次数累加)
即统计主机A到主机B的所有跨主机进程访问总次数(每次进程访问都算一次)。
cypher
// 匹配跨主机的进程访问路径
MATCH
(h1:Host)-[:RUNS]->(p1:Process)-[call:CALLS]->(p2:Process)<-[:RUNS]-(h2:Host)
WHERE
h1.host_id <> h2.host_id
// 按主机对分组,统计访问次数
WITH
h1.host_id AS source_host,
h2.host_id AS target_host,
count(call) AS access_count // 统计进程访问的总次数
RETURN
source_host,
target_host,
access_count
ORDER BY access_count DESC // 按访问次数降序排列
结果示例:
| source_host | target_host | access_count |
|---|---|---|
| 192.168.1.1 | 192.168.1.2 | 156 |
| 192.168.1.2 | 192.168.1.3 | 89 |
场景3:统计"主机对之间的 unique 进程访问对数量"
即统计主机A到主机B有多少对不同的进程(P1→P2)在进行访问(去重进程对)。
cypher
// 匹配跨主机的进程访问路径
MATCH
(h1:Host)-[:RUNS]->(p1:Process)-[:CALLS]->(p2:Process)<-[:RUNS]-(h2:Host)
WHERE
h1.host_id <> h2.host_id
// 提取进程对(p1→p2),按主机对去重统计
WITH
h1.host_id AS source_host,
h2.host_id AS target_host,
p1.process_id AS source_process,
p2.process_id AS target_process
// 先去重进程对,再统计主机对的 unique 进程访问数
WITH
source_host,
target_host,
count(source_process, target_process) AS unique_process_pairs
RETURN
source_host,
target_host,
unique_process_pairs
ORDER BY unique_process_pairs DESC
结果示例:
| source_host | target_host | unique_process_pairs |
|---|---|---|
| 192.168.1.1 | 192.168.1.2 | 8 |
| 192.168.1.2 | 192.168.1.3 | 3 |
四、优化建议
-
创建索引提升性能 :
为节点的唯一标识属性创建索引,加速路径匹配:
cypherCREATE INDEX IF NOT EXISTS FOR (h:Host) ON (h.host_id); CREATE INDEX IF NOT EXISTS FOR (p:Process) ON (p.process_id); -
限制查询范围(可选) :
若数据量庞大,可通过时间范围(若关系有
timestamp属性)或特定主机过滤:cypher// 仅统计2023年之后的访问 MATCH (h1:Host)-[:RUNS]->(p1:Process)-[call:CALLS]->(p2:Process)<-[:RUNS]-(h2:Host) WHERE h1.host_id <> h2.host_id AND call.timestamp >= datetime('2023-01-01') // ... 后续统计逻辑 -
可视化主机访问关系 :
若需要在Neo4j Browser中可视化主机间关系,可创建临时的主机访问关系(统计后可删除):
cypher// 创建临时的:ACCESS关系用于可视化 MATCH (h1:Host)-[:RUNS]->(p1:Process)-[:CALLS]->(p2:Process)<-[:RUNS]-(h2:Host) WHERE h1.host_id <> h2.host_id MERGE (h1)-[r:ACCESS]->(h2) ON CREATE SET r.count = 1 ON MATCH SET r.count = r.count + 1;
总结
通过匹配 Host→Process→Process←Host 路径,可提取主机间的间接访问关系。根据业务需求(是否统计次数、是否去重进程对),调整 count() 的使用即可实现灵活统计。核心是利用Neo4j的路径匹配能力,将进程级的访问关系"聚合"为主机级的访问关系。