Criar um gráfico com uma visualização SQL

Saiba como criar um gráfico usando visualizações SQL. Este documento fornece instruções detalhadas e exemplos de código para definir visualizações e usá-las para definir tabelas de nós e arestas. Confira exemplos com amostras de código que demonstram casos de uso para criar gráficos com visualizações. Para saber mais sobre como usar visualizações para criar um gráfico de propriedades, incluindo benefícios e considerações, consulte Visão geral dos gráficos criados com visualizações SQL.

Antes de começar

Para criar um gráfico, você precisa:

  1. Verifique se o ambiente do Spanner Graph está configurado.

  2. Saiba como os esquemas do Spanner Graph funcionam.

Criar um gráfico usando visualizações

Para criar um gráfico usando visualizações:

  1. Defina visualizações para seu gráfico. Verifique se as visualizações seguem um dos padrões obrigatórios. Para mais informações, consulte Criar uma visualização.

  2. Use suas visualizações nas cláusulas NODE TABLES e EDGE TABLES da instrução CREATE PROPERTY GRAPH para criar um gráfico.

  3. Inclua a cláusula KEY na instrução CREATE PROPERTY GRAPH. A cláusula KEY especifica as colunas da visualização de origem que identificam exclusivamente cada elemento do gráfico.

Exemplo: criar um gráfico usando visualizações

Este exemplo cria as seguintes visualizações nas tabelas Customer e Account: AsiaCustomer, AsiaBankAccount e AsiaAccountsOwnership. Em seguida, o exemplo usa essas visualizações para criar o seguinte em um gráfico:

  • Crie a tabela de nós Customer usando a visualização AsiaCustomer.

  • Crie a tabela de nós Account usando a visualização AsiaBankAccount.

  • Crie a tabela de arestas Owns usando a visualização AsiaAccountsOwnership. Essa aresta conecta nós Customer com nós Account.

Etapa 1: criar as tabelas

Primeiro, crie as tabelas de dados. O código a seguir cria as tabelas Customer e Account.

CREATE TABLE Customer (
  customer_id INT64 NOT NULL,
  name STRING(MAX),
  address_continent STRING(MAX),
  address_country STRING(MAX),
) PRIMARY KEY(customer_id);

CREATE TABLE Account (
  account_id INT64 NOT NULL,
  customer_id INT64 NOT NULL,
  account_type STRING(MAX),
  balance INT64,
  create_time TIMESTAMP,
  address_continent STRING(MAX),
  address_country STRING(MAX),
  CONSTRAINT FK_CustomerId FOREIGN KEY (customer_id)
    REFERENCES Customer (customer_id)
) PRIMARY KEY(account_id);

Etapa 2: criar as visualizações

Em seguida, crie visualizações para transformar ou filtrar dados das tabelas. Essas visualizações filtram as tabelas para incluir apenas clientes e contas na Ásia. As visualizações usadas para criar elementos de gráfico precisam garantir que as linhas na visualização sejam exclusivas.

-- View for 'Customer' nodes, filtered for Asia
CREATE VIEW AsiaCustomer
  SQL SECURITY INVOKER AS
    SELECT customer.customer_id, customer.name
    FROM Customer customer
    WHERE LOWER(customer.address_continent) = "asia";

-- View for 'Account' nodes, filtered for Asia.
CREATE VIEW AsiaBankAccount
  SQL SECURITY INVOKER AS
    SELECT account.account_id, account.balance, account.account_type, account.create_time
    FROM Account account
    WHERE LOWER(account.address_continent) = "asia";

-- View for 'Owns' edges, connecting customers to accounts in Asia.
CREATE VIEW AsiaAccountsOwnership
  SQL SECURITY INVOKER AS
    SELECT account.customer_id, account.account_id
    FROM Account account
    WHERE LOWER(account.address_continent) = "asia";

Etapa 3: criar o gráfico de propriedades

Agora, crie o AsiaFinGraph usando as visualizações criadas. A instrução CREATE PROPERTY GRAPH inclui a cláusula KEY para cada definição de elemento do gráfico e especifica colunas que identificam exclusivamente os elementos do gráfico.

CREATE PROPERTY GRAPH AsiaFinGraph
  NODE TABLES (
    AsiaCustomer AS Customer KEY(customer_id),
    AsiaBankAccount AS Account KEY(account_id)
  )
  EDGE TABLES (
    AsiaAccountsOwnership AS Owns
      KEY(customer_id, account_id)
      SOURCE KEY (customer_id) REFERENCES Customer (customer_id)
      DESTINATION KEY (account_id) REFERENCES Account (account_id)
  );

Exemplos de casos de uso

As visualizações SQL oferecem benefícios em relação ao uso de tabelas para elementos de gráfico de propriedades. Os exemplos a seguir demonstram alguns casos de uso para definir elementos de gráfico com visualizações em vez de tabelas.

Exemplo: aplicar controle de acesso refinado a dados de gráficos

Para aplicar a segurança no nível da linha aos dados do gráfico, defina as tabelas de nós ou arestas usando visualizações de direitos do definidor. A visualização expõe um subconjunto permitido dos dados subjacentes ao gráfico.

Por exemplo, para restringir o acesso ao gráfico apenas a funcionários de um centro de custo de engenharia, crie uma vista EngineerEmployeeView e conceda permissões SELECT nela a uma função engineering_data_reader usando a cláusula GRANT.

Ao definir uma tabela de nós de gráfico usando essa visualização, os usuários que executam consultas de gráfico com a função engineering_data_reader só podem ver as linhas filtradas pela visualização, que incluem funcionários de engenharia.

-- The table containing all employee data.
CREATE TABLE Employee (
  id INT64 NOT NULL,
  cost_center STRING(MAX),
  job_title STRING(MAX),
  office STRING(MAX)
) PRIMARY KEY (id);

-- The definer's rights view that filters for engineering employees.
CREATE VIEW EngineerEmployeeView SQL SECURITY DEFINER AS
  SELECT e.id, e.cost_center, e.job_title, e.office
  FROM Employee e
  WHERE LOWER(e.cost_center) = "engineering";

-- The role that is granted to read the view.
CREATE ROLE engineering_data_reader;
GRANT SELECT ON VIEW EngineerEmployeeView TO ROLE engineering_data_reader;

-- The graph that uses definer's rights view.
CREATE PROPERTY GRAPH EngineeringGraph
  NODE TABLES (
    EngineerEmployeeView KEY(id)
  );

Exemplo: elementos de gráfico derivados do modelo

É possível usar visualizações para definir elementos de gráfico que exigem transformações de dados. Um benefício importante é que a visualização define a transformação, então não é necessário manter uma tabela separada para os dados derivados.

Por exemplo, é possível UNNEST dados de uma coluna ARRAY (ou um campo de matriz em uma coluna JSON) para modelar várias relações de aresta de uma única linha.

No exemplo de esquema de cadeia de suprimentos a seguir, uma tabela Parts armazena uma lista de subcomponentes em uma matriz dependent_parts. Uma visualização pode usar o operador UNNEST para transformar cada elemento dessa matriz em linhas distintas. Essa visualização pode servir como uma tabela de arestas, permitindo modelar uma aresta PartDependsOnPart para representar relações de dependência entre partes.

-- Parts table with an ARRAY of dependent parts.
CREATE TABLE Parts (
  part_id INT64 NOT NULL,
  dependent_parts ARRAY<INT64>
) PRIMARY KEY (part_id);

-- A view that unnests the dependent_parts array.
-- GROUP BY ensures uniqueness for the graph element KEY.
CREATE VIEW PartDependsOnPart SQL SECURITY INVOKER AS
  SELECT p.part_id, dependent_part_id
  FROM Parts AS p,
    UNNEST(p.dependent_parts) AS dependent_part_id
  GROUP BY p.part_id, dependent_part_id;

-- Graph modeling the part dependency relationship.
CREATE PROPERTY GRAPH SupplyChainGraph
  NODE TABLES (
    Parts
  )
  EDGE TABLES (
    PartDependsOnPart KEY (part_id, dependent_part_id)
      SOURCE KEY (part_id) REFERENCES Parts(part_id)
      DESTINATION KEY (dependent_part_id) REFERENCES Parts(part_id)
  );

Exemplo: transição de dados sem esquema

O gerenciamento de dados sem esquema permite criar uma definição de gráfico flexível sem tipos de nós e arestas predefinidos. Embora o gerenciamento de dados sem esquema ofereça flexibilidade, talvez seja necessário fazer a transição para uma estrutura mais formal à medida que os dados se tornam mais definidos. Uma estrutura mais formal expõe as relações de nós e arestas, rótulos e propriedades do grafo no esquema, o que reduz a necessidade de exploração manual de dados para entender o esquema do grafo.

Você pode usar visualizações para formalizar os tipos de nós e arestas sem migrar os dados subjacentes. Por exemplo, é possível fazer a transição de um modelo típico sem esquema que usa tabelas canônicas GraphNode e GraphEdge. Para isso, crie visualizações que extraem os dados das suas tabelas sem esquema:

  1. Defina uma visualização para cada tipo de nó e aresta que você quer formalizar (por exemplo, Person ou WorksFor). Na visualização, filtre os dados pelo rótulo (por exemplo, WHERE n_label = "person") e converta as propriedades da coluna JSON em tipos de dados específicos (por exemplo, STRING(prop.name) AS name).

  2. Defina um novo gráfico de propriedades em que NODE TABLES e EDGE TABLES referenciam as visualizações tipadas que você acabou de criar.

Um gráfico sem esquema oferece melhor desempenho do que um gráfico formalizado para algumas consultas (por exemplo, um padrão de caminho quantificado com vários tipos de arestas). Se metadados formalizados forem importantes para seu caso de uso, use visualizações para fazer a transição de um grafo sem esquema para um esquema tipado. Você também pode usar um gráfico sem esquema para alguns casos de uso e um gráfico de esquema tipado para outros. Para mais informações, consulte Escolher um design de esquema com base em consultas de gráficos.

O exemplo a seguir demonstra o fluxo de trabalho para fazer a transição de um gráfico sem esquema para um gráfico formalizado em quatro etapas:

  1. Defina as tabelas canônicas GraphNode e GraphEdge para o modelo sem esquema.

  2. Crie um gráfico inicial e flexível nessas tabelas sem esquema.

  3. Defina visualizações tipadas (Person, Company, WorksFor) que extraem e formalizam os dados das tabelas sem esquema.

  4. Crie o gráfico final fortemente tipado que usa essas visualizações como tabelas de nós e arestas.

-- 1. Create the canonical tables for a schemaless model.
CREATE TABLE GraphNode (
  id INT64 NOT NULL,
  label STRING(MAX) NOT NULL,
  properties JSON
) PRIMARY KEY (id);

CREATE TABLE GraphEdge (
  id INT64 NOT NULL,
  dest_id INT64 NOT NULL,
  edge_id INT64 NOT NULL,
  label STRING(MAX) NOT NULL,
  properties JSON
) PRIMARY KEY (id, dest_id, edge_id),
  INTERLEAVE IN PARENT GraphNode;

-- 2. Define a schemaless graph.
CREATE PROPERTY GRAPH FinGraph
  NODE TABLES (
    GraphNode
      DYNAMIC LABEL (label)
      DYNAMIC PROPERTIES (properties)
  )
  EDGE TABLES (
    GraphEdge
      SOURCE KEY (id) REFERENCES GraphNode(id)
      DESTINATION KEY (dest_id) REFERENCES GraphNode(id)
      DYNAMIC LABEL (label)
      DYNAMIC PROPERTIES (properties)
  );

-- 3. Define typed views that extract and formalize the data.
--    Convert JSON fields to primitive types (for example, INT64, STRING) to
--    ensure type safety.
CREATE VIEW Person SQL SECURITY INVOKER AS
  SELECT n.id, STRING(n.properties.name) AS name, INT64(n.properties.age) AS age
  FROM GraphNode n WHERE n.label = "person";

CREATE VIEW Company SQL SECURITY INVOKER AS
  SELECT n.id, STRING(n.properties.name) AS company_name, BOOL(n.properties.is_public) AS is_public
  FROM GraphNode n WHERE n.label = "company";

CREATE VIEW WorksFor SQL SECURITY INVOKER AS
  SELECT e.id AS person_id, e.dest_id AS company_id, e.edge_id AS edge_id, STRING(e.properties.since) AS since
  FROM GraphEdge e
  WHERE e.label = "worksfor";

-- 4. Create the final, formalized graph from the typed views.
CREATE PROPERTY GRAPH typed_formalized_graph
  NODE TABLES (
    Person KEY(id)
      PROPERTIES (name, age),
    Company KEY(id)
      PROPERTIES (company_name, is_public)
  )
  EDGE TABLES(
    WorksFor KEY(person_id, company_id, edge_id)
      SOURCE KEY (person_id) REFERENCES Person(id)
      DESTINATION KEY (company_id) REFERENCES Company(id)
      PROPERTIES (since)
  );

A seguir