다음을 통해 공유


make-graph 연산자

적용 대상: ✅Microsoft Fabric

연산자는 make-graph 에지 및 노드의 테이블 형식 입력에서 그래프 구조를 작성합니다.

구문

Edges|make-graph SourceNodeId--> TargetNodeId [ withNodes1on NodeId1 [,Nodes2onNodeId2 ]]

가장자리|make-graphSourceNodeId-->TargetNodeId [ with_node_id=NodeIdPropertyName ]

가장자리|make-graphSourceNodeId-->TargetNodeId [ withNodes1onNodeId1 [,Nodes2onNodeId2 ]] partitioned-byPartitionColumn(GraphOperator)

매개 변수

이름 Type 필수 설명
가장자리 string ✔️ 그래프의 가장자리를 포함하는 테이블 형식 원본으로, 각 행은 그래프의 가장자리를 나타냅니다.
SourceNodeId string ✔️ 에지의 원본 노드 ID가 있는 Edge 의 열입니다.
TargetNodeId string ✔️ 에지의 대상 노드 ID가 있는 Edge 의 열입니다.
nodes1 Nodes2 string 그래프에 있는 노드의 속성을 포함하는 테이블 형식 식입니다.
nodesId1 NodesId2 string 노드 ID가 Nodes1노드 ID가 있는 해당 열은 각각 Nodes2 .
NodeIdPropertyName string 그래프 노드의 노드 ID에 대한 속성 이름입니다.
PartitionColumn string 그래프를 분할할 열입니다. 이 열의 각 고유 값에 대해 별도의 그래프를 만듭니다.
GraphOperator string 분할된 각 그래프에 적용할 그래프 연산자입니다.

반품

연산자는 make-graph 그래프 식을 반환하고 그래프 연산뒤에 와야 합니다. 원본 Edges 식의 각 행은 행의 열 값인 속성을 사용하여 그래프의 가장자리가 됩니다. Nodes 테이블 형식 식의 각 행은 행의 열 값인 속성을 사용하여 그래프의 노드가 됩니다. Edges 테이블에 표시되지만 노드 테이블에 해당 행이 없는 노드는 해당 노드 ID와 빈 속성을 가진 노드로 만들어집니다.

절을 partitioned-by 사용하는 경우 지정된 PartitionColumn의 각 고유 값에 대해 별도의 그래프가 만들어집니다. 지정된 GraphOperator 는 분할된 각 그래프에 독립적으로 적용되고 결과는 단일 출력으로 결합됩니다. 이는 동일한 그래프 구조 및 분석 논리를 유지하면서 각 테넌트의 데이터를 개별적으로 분석하려는 다중 테넌트 시나리오에 특히 유용합니다.

중요합니다

절을 partitioned-by 사용하는 경우 Edges 테이블과 모든 노드 테이블 모두 파티션 열을 포함해야 합니다.

참고 항목

각 노드에는 고유 식별자가 있습니다. Nodes1Nodes2 테이블 모두에 동일한 노드 ID가 나타나면 해당 속성을 병합하여 단일 노드가 만들어집니다. 동일한 노드에 대해 충돌하는 속성 값이 있는 경우 값 중 하나가 임의로 선택됩니다.

사용자는 다음과 같은 방법으로 노드 정보를 처리할 수 있습니다.

  1. 노드 정보가 필요하지make-graph 않습니다. 원본 및 대상을 사용하여 완료합니다.
  2. 명시적 노드 속성: "withNodes1 NodeId1
  3. 기본 노드 식별자: "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

출력

공격자 손상됨 시스템
Mallory Bob Trent

기본 노드 식별자

다음 예제에서는 기본 노드 식별자로 속성을 사용 하 여 가장자리 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

출력

공격자 손상됨 시스템
Mallory Bob Trent

분할된 그래프

이 예제에서는 절을 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 거주자
Bob Smith(CompanyA) [
"CompanyA",
"CompanyA"
]
다이애나 핀치 (CompanyA)
헨리 데이비스 (CompanyB) [
"CompanyB",
"CompanyB"
]
그레이스 리 (CompanyB)