運算子 make-graph 會從邊緣和節點的表格式輸入建置圖形結構。
語法
Edges|make-graph [ Nodes1--> NodeId1 [withon Nodes2,NodeId2 ]]
邊緣|make-graph來源節點標識符-->TargetNodeId [ with_node_id=NodeId 屬性名稱 ]
邊緣|make-graph來源節點標識符-->TargetNodeId [ with節點 1on節點 Id1 [,節點 2on 節點Id2 ]] partitioned-byPartitionColumn(圖形運算子)
參數
| 姓名 | 類型 | 必要 | 描述 |
|---|---|---|---|
| 邊緣 | string |
✔️ | 包含圖形邊緣的表格式來源,每個數據列都代表圖形中的邊緣。 |
| SourceNodeId | string |
✔️ | Edge 中具有邊緣來源節點標識碼的數據行。 |
| TargetNodeId | string |
✔️ | Edge 中具有邊緣目標節點標識碼的數據行。 |
| Nodes1Nodes2 | string |
包含圖形中節點屬性的表格式表達式。 | |
| NodesId1NodesId2 | string |
Nodes1中節點標識碼的對應數據行,分別 Nodes2。 | |
| NodeIdPropertyName | string |
圖形節點上節點標識碼的屬性名稱。 | |
| 分割區資料行 | string |
要分割圖表的資料行。 為此欄中的每個唯一值建立個別的圖表。 | |
| 圖形運算子 | string |
要套用至每個分割圖形的圖形運算子。 |
傳回
make-graph運算符會傳回圖表表達式,且後面必須接著圖形運算元。 來源 Edges 運算式中的每個數據列都會成為圖形中的邊緣,其中包含數據列數據行值的屬性。 Nodes 表格式表示式中的每個數據列都會成為圖形中的節點,其中包含數據列數據行值的屬性。 出現在 Edges 數據表但 Nodes 數據表中沒有對應數據列的節點會建立為具有對應節點識別碼和空白屬性的節點。
使用子 partitioned-by 句時,會針對指定 PartitionColumn 中的每個唯一值建立個別的圖形。 然後,指定的 GraphOperator 會獨立套用至每個分割的圖形,並將結果合併成單一輸出。 這對於想要個別分析每個租用戶資料,同時維護相同的圖形結構和分析邏輯的多租用戶案例特別有用。
這很重要
使用子 partitioned-by 句時, Edge 資料表和所有 節點 資料表都必須包含分割區資料行。
注意
每個節點都有唯一標識碼。 如果 Nodes1 和 Nodes2 資料表中出現相同的節點識別碼,則會藉由合併其屬性來建立單一節點。 如果相同節點有衝突的屬性值,則會任意選擇其中一個值。
使用者可以以下欄方式處理節點資訊:
-
不需要節點資訊:
make-graph使用來源和目標完成。 -
明確節點屬性:最多使用兩個表格式表達式,使用 “
withNodeId1 [onNodeId2 ]。” -
默認節點標識碼:使用 「
with_node_id=DefaultNodeId」。。
範例
邊緣和節點圖形
下列範例會從邊緣和節點數據表建置圖形。 節點代表人員和系統,邊緣代表節點之間的不同關聯性。 運算子 make-graph 會建置圖形。 然後, graph-match 運算符會與圖形模式搭配使用,以搜尋導致系統 "Trent" 節點的攻擊路徑。
let nodes = datatable(name:string, type:string, age:int)
[
"Alice", "Person", 23,
"Bob", "Person", 31,
"Eve", "Person", 17,
"Mallory", "Person", 29,
"Trent", "System", 99
];
let edges = datatable(Source:string, Destination:string, edge_type:string)
[
"Alice", "Bob", "communicatesWith",
"Alice", "Trent", "trusts",
"Bob", "Trent", "hasPermission",
"Eve", "Alice", "attacks",
"Mallory", "Alice", "attacks",
"Mallory", "Bob", "attacks"
];
edges
| make-graph Source --> Destination with nodes on name
| graph-match (mallory)-[attacks]->(compromised)-[hasPermission]->(trent)
where mallory.name == "Mallory" and trent.name == "Trent" and attacks.edge_type == "attacks" and hasPermission.edge_type == "hasPermission"
project Attacker = mallory.name, Compromised = compromised.name, System = trent.name
輸出
| 攻擊者 | 遭洩漏 | 系統 |
|---|---|---|
| 馬婁裡 | Bob | 特 倫 特 |
默認節點識別碼
下列範例只會使用邊緣建置圖形,並將 name 屬性當做默認節點標識碼。 從邊緣表格式表示式建立圖形時,此方法很有用,可確保節點標識碼可供後續 graph-match 運算符的條件約束區段使用。
let edges = datatable(source:string, destination:string, edge_type:string)
[
"Alice", "Bob", "communicatesWith",
"Alice", "Trent", "trusts",
"Bob", "Trent", "hasPermission",
"Eve", "Alice", "attacks",
"Mallory", "Alice", "attacks",
"Mallory", "Bob", "attacks"
];
edges
| make-graph source --> destination with_node_id=name
| graph-match (mallory)-[attacks]->(compromised)-[hasPermission]->(trent)
where mallory.name == "Mallory" and trent.name == "Trent" and attacks.edge_type == "attacks" and hasPermission.edge_type == "hasPermission"
project Attacker = mallory.name, Compromised = compromised.name, System = trent.name
輸出
| 攻擊者 | 遭洩漏 | 系統 |
|---|---|---|
| 馬婁裡 | Bob | 特 倫 特 |
分割圖
此範例示範如何使用 partitioned-by 子句來分析多租用戶社交網路。 子 partitioned-by 句會針對分割區資料行中的每個唯一值建立個別的圖形 (在此案例中為 tenantId),將圖形運算子獨立套用至每個分割區,並結合結果。
// Nodes table representing users across multiple tenants (organizations)
let nodes = datatable(userId:string, tenantId:string, name:string, department:string, role:string, location:dynamic)
[
// Tenant: CompanyA - San Francisco Bay Area
"u001", "CompanyA", "Alice Johnson", "Engineering", "Senior Developer", dynamic({"type": "Point", "coordinates": [-122.4194, 37.7749]}),
"u002", "CompanyA", "Bob Smith", "Engineering", "Team Lead", dynamic({"type": "Point", "coordinates": [-122.4094, 37.7849]}),
"u003", "CompanyA", "Charlie Black", "Marketing", "Manager", dynamic({"type": "Point", "coordinates": [-122.4294, 37.7649]}),
"u004", "CompanyA", "Diana Finch", "HR", "Director", dynamic({"type": "Point", "coordinates": [-122.3994, 37.7949]}),
"u005", "CompanyA", "Eve Wilson", "Engineering", "Junior Developer", dynamic({"type": "Point", "coordinates": [-122.4394, 37.7549]}),
// Tenant: CompanyB - New York Area
"u006", "CompanyB", "Frank Miller", "Sales", "Account Manager", dynamic({"type": "Point", "coordinates": [-74.0060, 40.7128]}),
"u007", "CompanyB", "Grace Lee", "Engineering", "Senior Developer", dynamic({"type": "Point", "coordinates": [-74.0160, 40.7228]}),
"u008", "CompanyB", "Henry Davis", "Marketing", "Specialist", dynamic({"type": "Point", "coordinates": [-73.9960, 40.7028]}),
"u009", "CompanyB", "Ivy Chen", "Engineering", "Team Lead", dynamic({"type": "Point", "coordinates": [-74.0260, 40.7328]}),
"u010", "CompanyB", "Jack Thompson", "Operations", "Manager", dynamic({"type": "Point", "coordinates": [-73.9860, 40.6928]}),
// Tenant: CompanyC - Austin Area
"u011", "CompanyC", "Kate Anderson", "Finance", "Analyst", dynamic({"type": "Point", "coordinates": [-97.7431, 30.2672]}),
"u012", "CompanyC", "Liam Murphy", "Engineering", "Architect", dynamic({"type": "Point", "coordinates": [-97.7331, 30.2772]}),
"u013", "CompanyC", "Maya Patel", "Product", "Manager", dynamic({"type": "Point", "coordinates": [-97.7531, 30.2572]}),
"u014", "CompanyC", "Noah Garcia", "Engineering", "Developer", dynamic({"type": "Point", "coordinates": [-97.7631, 30.2472]}),
"u015", "CompanyC", "Olivia Rodriguez", "Marketing", "Director", dynamic({"type": "Point", "coordinates": [-97.7231, 30.2872]})
];
// Edges table representing relationships/interactions between users
let edges = datatable(sourceUserId:string, targetUserId:string, tenantId:string, relationshipType:string, strength:int)
[
// CompanyA relationships
"u001", "u002", "CompanyA", "reportsTo", 9,
"u005", "u002", "CompanyA", "reportsTo", 8,
"u002", "u003", "CompanyA", "collaborates", 6,
"u001", "u005", "CompanyA", "mentors", 7,
"u003", "u004", "CompanyA", "collaborates", 5,
"u001", "u003", "CompanyA", "communicates", 4,
// CompanyB relationships
"u007", "u009", "CompanyB", "reportsTo", 9,
"u006", "u010", "CompanyB", "reportsTo", 8,
"u008", "u006", "CompanyB", "collaborates", 6,
"u009", "u010", "CompanyB", "communicates", 5,
"u007", "u008", "CompanyB", "mentors", 7,
"u006", "u007", "CompanyB", "collaborates", 6,
// CompanyC relationships
"u014", "u012", "CompanyC", "reportsTo", 9,
"u012", "u013", "CompanyC", "collaborates", 7,
"u011", "u013", "CompanyC", "collaborates", 6,
"u013", "u015", "CompanyC", "reportsTo", 8,
"u012", "u015", "CompanyC", "communicates", 5,
"u011", "u014", "CompanyC", "mentors", 6
];
edges
| make-graph sourceUserId --> targetUserId with nodes on userId partitioned-by tenantId (
graph-match cycles=none (n1)-[e*2..4]->(n2)
where n1.userId != n2.userId and all(e, relationshipType == "collaborates") and
geo_distance_2points(todouble(n1.location.coordinates[0]), todouble(n1.location.coordinates[1]),
todouble(n2.location.coordinates[0]), todouble(n2.location.coordinates[1])) < 10000
project Start = strcat(n1.name, " (", n1.tenantId, ")"), Tenants = map(e, tenantId), End = strcat(n2.name, " (", n2.tenantId, ")")
)
| Start | 租戶 | 結束 |
|---|---|---|
| 鮑勃·史密斯(A公司) | [ “A公司”, “A公司” ] |
戴安娜·芬奇(A公司) |
| 亨利·戴維斯(B公司) | [ “B公司”, “B公司” ] |
Grace Lee (B公司) |