Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aplica-se a: ✅Microsoft Fabric✅Azure Data Explorer✅Azure Monitor✅Microsoft Sentinel
O make-graph operador constrói uma estrutura de grafo a partir de entradas tabulares de arestas e nós.
Sintaxe
Bordas|make-graph SourceNodeId --> TargetNodeId [ withon [ ,
Bordas|make-graphSourceNodeId-->TargetNodeId [ with_node_id=NodeIdPropertyName ]
Bordas|make-graphSourceNodeId-->TargetNodeId [ withNodes1onNodeId1 [,Nodes2onNodeId2 ]] partitioned-byPartitionColumn(GraphOperator)
Parâmetros
| Nome | Tipo | Obrigatória | Descrição |
|---|---|---|---|
| Bordas | string |
✔️ | A fonte tabular que contém as bordas do gráfico, cada linha representa uma borda no gráfico. |
| Código-fonte | string |
✔️ | A coluna em Edges com os IDs de nó de origem dos Edges. |
| TargetNodeId | string |
✔️ | A coluna em Edges com os IDs de nó de destino dos Edges. |
| Nós1, Nós2 | string |
As expressões tabulares que contêm as propriedades dos nós no grafo. | |
| nodesId1, nodesId2 | string |
As colunas correspondentes com as IDs do nó em Nós1, Nós2 respectivamente. | |
| NodeIdPropertyName | string |
O nome da propriedade da ID do nó nos nós do grafo. | |
| PartitionColumn | string |
A coluna pela qual particionar o grafo. Cria grafos separados para cada valor exclusivo nesta coluna. | |
| GraphOperator | string |
O operador de grafo a ser aplicado a cada grafo particionado. |
Devoluções
O make-graph operador retorna uma expressão de grafo e deve ser seguido por um operador de grafo. Cada linha na expressão Edges de origem se torna uma borda no gráfico com propriedades que são os valores de coluna da linha. Cada linha na expressão tabular Nós se torna um nó no gráfico com propriedades que são os valores de coluna da linha. Os nós que aparecem na tabela Edges , mas não têm uma linha correspondente na tabela Nós , são criados como nós com o ID de nó correspondente e propriedades vazias.
Ao usar a partitioned-by cláusula, grafos separados são criados para cada valor exclusivo no PartitionColumn especificado. O GraphOperator especificado é aplicado a cada grafo particionado de forma independente e os resultados são combinados em uma única saída. Isso é particularmente útil para cenários multilocatários em que você deseja analisar os dados de cada locatário separadamente, mantendo a mesma estrutura de grafo e lógica de análise.
Importante
Ao usar a partitioned-by cláusula, a tabela Bordas e todas as tabelas de nós devem conter a coluna de partição.
Observação
Cada nó tem um identificador exclusivo. Se o mesmo ID de nó aparecer nas tabelas Nodes1 e Nodes2 , um único nó será criado mesclando suas propriedades. Se houver valores de propriedade conflitantes para o mesmo nó, um dos valores será escolhido arbitrariamente.
Os usuários podem lidar com informações de nó das seguintes maneiras:
-
Nenhuma informação de nó necessária:
make-graphé concluída com origem e destino. -
Propriedades explícitas do nó: use até duas expressões tabulares usando "
withon[,]". -
Identificador de nó padrão: use "
with_node_id=DefaultNodeId".
Exemplo
Gráfico de arestas e nós
O exemplo a seguir cria um grafo a partir de tabelas de bordas e nós. Os nós representam pessoas e sistemas, e as bordas representam diferentes relacionamentos entre nós. O make-graph operador constrói o gráfico. Em seguida, o graph-match operador é usado com um padrão de gráfico para procurar caminhos de ataque que levam ao nó do "Trent" sistema.
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
Saída
| Invasor | Comprometido | Sistema |
|---|---|---|
| Mallory | Bob | Trent |
Identificador de nó padrão
O exemplo a seguir cria um grafo usando apenas bordas, com a name propriedade como o identificador de nó padrão. Essa abordagem é útil ao criar um gráfico a partir de uma expressão tabular de bordas, garantindo que o identificador de nó esteja disponível para a seção de restrições do operador subsequente 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
Saída
| Invasor | Comprometido | Sistema |
|---|---|---|
| Mallory | Bob | Trent |
Grafo particionado
Este exemplo demonstra o uso da partitioned-by cláusula para analisar uma rede social multilocatário. A partitioned-by cláusula cria grafos separados para cada valor exclusivo na coluna de partição (nesse caso, tenantId), aplica o operador de grafo a cada partição de forma independente e combina os resultados.
// 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 | Inquilinos | participante |
|---|---|---|
| Bob Smith (CompanyA) | [ "CompanyA", "CompanyA" ] |
Diana Finch (CompanyA) |
| Henry Davis (CompanyB) | [ "CompanyB", "CompanyB" ] |
Grace Lee (CompanyB) |