Crie um gráfico a partir de uma vista SQL

Saiba como criar um gráfico com vistas SQL. Este documento fornece instruções passo a passo e exemplos de código para definir vistas e usá-las para definir tabelas de nós e arestas. Explore exemplos com código de amostra que demonstram exemplos de utilização para criar gráficos com visualizações. Para saber mais sobre a utilização de visualizações para criar um gráfico de propriedades, incluindo vantagens e considerações, consulte o artigo Vista geral dos gráficos criados a partir de visualizações SQL.

Antes de começar

Para criar um gráfico, tem de:

  1. Certifique-se de que o ambiente do Spanner Graph está configurado.

  2. Familiarize-se com o funcionamento dos esquemas de grafos do Spanner.

Crie um gráfico com visualizações

Para criar um gráfico com visualizações de páginas:

  1. Defina vistas para o seu gráfico. Certifique-se de que as suas visualizações seguem um dos padrões de visualização obrigatórios. Para mais informações, consulte Crie uma vista.

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

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

Exemplo: crie um gráfico com visualizações

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

  • Crie a tabela de nós Customer com a vista AsiaCustomer.

  • Crie a tabela de nós Account com a vista AsiaBankAccount.

  • Crie a tabela de arestas Owns através da vista AsiaAccountsOwnership. Esta aresta liga os nós Customer aos nós Account.

Passo 1: crie as tabelas

Primeiro, crie as tabelas de dados. O código seguinte 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);

Passo 2: crie as visualizações

Em seguida, crie visualizações para transformar ou filtrar dados das tabelas. Estas vistas filtram as tabelas para incluir apenas clientes e contas na Ásia. As visualizações usadas para criar elementos de gráficos têm de garantir que as linhas na visualização são únicas.

-- 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";

Passo 3: crie o gráfico de propriedades

Agora, crie o AsiaFinGraph usando as visualizações que criou. A declaração CREATE PROPERTY GRAPH inclui a cláusula KEY para cada definição de elemento do gráfico para especificar 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 utilização

As vistas SQL oferecem vantagens em relação à utilização de tabelas para elementos de gráficos de propriedades. Os exemplos seguintes demonstram alguns exemplos de utilização para definir elementos de gráficos com vistas em vez de tabelas.

Exemplo: aplique o controlo de acesso aos dados do gráfico detalhado

Para aplicar a segurança ao nível da linha nos dados do gráfico, defina as tabelas de nós ou arestas com vistas de direitos do definidor. A vista expõe um subconjunto permitido dos dados subjacentes ao gráfico

Por exemplo, para restringir o acesso ao gráfico apenas aos funcionários de um centro de custos de engenharia, pode criar uma visualização EngineerEmployeeView e conceder autorizações SELECT na visualização a uma função engineering_data_reader através da cláusula GRANT.

Quando define uma tabela de nós do gráfico através desta vista, os utilizadores que executam consultas de gráficos com a função engineering_data_reader só podem ver as linhas filtradas pela vista, 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 grafos derivados de modelos

Pode usar vistas para definir elementos de gráficos que requerem transformações de dados. Uma vantagem fundamental é que a vista define a transformação, pelo que não tem de manter uma tabela separada para os dados derivados.

Por exemplo, pode UNNEST dados de uma coluna ARRAY (ou um campo de matriz numa coluna JSON) para modelar várias relações de arestas a partir de uma única linha.

No exemplo de esquema da cadeia de fornecimento seguinte, uma tabela Parts armazena uma lista de subcomponentes numa matriz dependent_parts. Uma vista pode usar o operador UNNEST para transformar cada elemento dessa matriz em linhas distintas. Esta vista pode, então, servir como uma tabela de arestas, permitindo-lhe modelar uma aresta PartDependsOnPart para representar relações de dependência entre as 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

A gestão de dados sem esquema permite-lhe criar uma definição de gráfico flexível sem tipos de nós e arestas predefinidos. Embora a gestão de dados sem esquema ofereça flexibilidade, pode ter de fazer a transição para uma estrutura mais formal à medida que os seus dados se tornam mais definidos. Uma estrutura mais formal expõe as relações de nós e arestas, as etiquetas e as propriedades do gráfico no esquema, o que reduz a necessidade de exploração manual de dados para compreender o esquema do gráfico.

Pode usar as vistas para formalizar os tipos de nós e arestas sem migrar os dados subjacentes. Por exemplo, pode fazer a transição de um modelo sem esquema típico que usa tabelas canónicas GraphNode e GraphEdge. Para o fazer, crie vistas que extraiam os dados das suas tabelas sem esquema:

  1. Defina uma vista para cada tipo de nó e aresta que quer formalizar (por exemplo, Person ou WorksFor). Na vista, filtre os dados pela respetiva etiqueta (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 onde NODE TABLES e EDGE TABLES fazem referência às visualizações de propriedades com tipo que acabou de criar.

Um gráfico sem esquema oferece um 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 os metadados formalizados forem importantes para o seu exemplo de utilização, pode usar as visualizações para fazer a transição de um gráfico sem esquema para um esquema com tipos. Também pode optar por usar um gráfico sem esquema para alguns exemplos de utilização e um gráfico de esquema com tipos para outros exemplos de utilização. Para mais informações, consulte o artigo Escolha um design de esquema com base em consultas de grafos.

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

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

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

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

  4. Crie o gráfico final com tipos fortes que usa estas vistas 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)
  );

O que se segue?