Crea un gráfico a partir de una vista de SQL

Aprende a crear un gráfico con vistas de SQL. En este documento, se proporcionan instrucciones paso a paso y ejemplos de código para definir vistas y usarlas para definir tablas de nodos y bordes. Explora ejemplos con código de muestra que demuestran casos de uso para crear gráficos con vistas. Para obtener más información sobre el uso de vistas para crear un gráfico de propiedades, incluidos los beneficios y las consideraciones, consulta Descripción general de los gráficos creados a partir de vistas de SQL.

Antes de comenzar

Para crear un gráfico, debes hacer lo siguiente:

  1. Asegúrate de que tu entorno de Spanner Graph esté configurado.

  2. Familiarízate con cómo funcionan los esquemas de Spanner Graph.

Crea un gráfico con vistas

Para crear un gráfico con vistas, haz lo siguiente:

  1. Define vistas para tu gráfico. Asegúrate de que tus vistas sigan uno de los patrones de vistas requeridos. Para obtener más información, consulta Crea una vista.

  2. Usa tus vistas en las cláusulas NODE TABLES y EDGE TABLES de la declaración CREATE PROPERTY GRAPH para crear un gráfico.

  3. Incluye la cláusula KEY en la sentencia CREATE PROPERTY GRAPH. La cláusula KEY especifica las columnas de la vista de origen que identifican de forma única cada elemento del gráfico.

Ejemplo: Crea un gráfico con vistas

En este ejemplo, se crean las siguientes vistas sobre las tablas Customer y Account: AsiaCustomer, AsiaBankAccount y AsiaAccountsOwnership. Luego, el ejemplo usa estas vistas para crear lo siguiente en un gráfico:

  • Crea la tabla de nodos Customer con la vista AsiaCustomer.

  • Crea la tabla de nodos Account con la vista AsiaBankAccount.

  • Crea la tabla de aristas Owns con la vista AsiaAccountsOwnership. Esta arista conecta los nodos Customer con los nodos Account.

Paso 1: Crea las tablas

Primero, crea las tablas de datos. El siguiente código crea las tablas Customer y 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);

Paso 2: Crea las vistas

A continuación, crea vistas para transformar o filtrar los datos de las tablas. Estas vistas filtran las tablas para incluir solo los clientes y las cuentas de Asia. Las vistas que se usan para crear elementos del gráfico deben garantizar que las filas de la vista sean ú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";

Paso 3: Crea el gráfico de propiedades

Ahora, crea el objeto AsiaFinGraph con las vistas que creaste. La sentencia CREATE PROPERTY GRAPH incluye la cláusula KEY para cada definición de elemento del gráfico con el objetivo de especificar las columnas que identifican de forma única los elementos del 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)
  );

Ejemplos de casos de uso

Las vistas de SQL ofrecen beneficios en comparación con el uso de tablas para los elementos de grafos de propiedades. En los siguientes ejemplos, se muestran algunos casos de uso para definir elementos de gráficos con vistas en lugar de tablas.

Ejemplo: Aplica un control de acceso detallado a los datos del gráfico

Para aplicar la seguridad a nivel de fila en los datos del gráfico, define tus tablas de nodos o bordes con vistas de derechos del definidor. La vista expone un subconjunto permitido de los datos subyacentes al gráfico.

Por ejemplo, para restringir el acceso al gráfico solo a los empleados de un centro de costos de ingeniería, puedes crear una vista EngineerEmployeeView y otorgar permisos SELECT en la vista a un rol engineering_data_reader con la cláusula GRANT.

Cuando defines una tabla de nodos del grafo con esta vista, los usuarios que ejecutan consultas de grafos con el rol de engineering_data_reader solo pueden ver las filas filtradas por la vista, que incluyen a los empleados de ingeniería.

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

Ejemplo: Elementos del gráfico derivados del modelo

Puedes usar vistas para definir elementos del gráfico que requieren transformaciones de datos. Un beneficio clave es que la vista define la transformación, por lo que no necesitas mantener una tabla separada para los datos derivados.

Por ejemplo, puedes UNNEST datos de una columna ARRAY (o un campo de array dentro de una columna JSON) para modelar varias relaciones de borde desde una sola fila.

En el siguiente ejemplo de esquema de cadena de suministro, una tabla Parts almacena una lista de subcomponentes en un array dependent_parts. Una vista puede usar el operador UNNEST para transformar cada elemento de ese array en filas distintas. Luego, esta vista puede servir como tabla de borde, lo que te permite modelar un borde de PartDependsOnPart para representar las relaciones de dependencia entre las 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)
  );

Ejemplo: Transición de datos sin esquema

La administración de datos sin esquema te permite crear una definición de gráfico flexible sin tipos de nodos ni bordes predefinidos. Si bien la administración de datos sin esquemas proporciona flexibilidad, es posible que debas realizar una transición a una estructura más formal a medida que tus datos se definan mejor. Una estructura más formal expone las relaciones, las etiquetas y las propiedades de los nodos y las aristas del gráfico en el esquema, lo que reduce la necesidad de explorar los datos de forma manual para comprender el esquema del gráfico.

Puedes usar vistas para formalizar los tipos de nodos y aristas sin migrar tus datos subyacentes. Por ejemplo, puedes hacer la transición de un modelo típico sin esquema que usa tablas canónicas GraphNode y GraphEdge. Para ello, crea vistas que extraigan los datos de tus tablas sin esquema:

  1. Define una vista para cada tipo de nodo y borde que desees formalizar (por ejemplo, Person o WorksFor). En la vista, filtra los datos por su etiqueta (por ejemplo, WHERE n_label = "person") y convierte las propiedades de la columna JSON en tipos de datos específicos (por ejemplo, STRING(prop.name) AS name).

  2. Define un nuevo gráfico de propiedades en el que NODE TABLES y EDGE TABLES hagan referencia a las vistas escritas que acabas de crear.

Un grafo sin esquema proporciona un mejor rendimiento que un grafo formalizado para algunas búsquedas (por ejemplo, un patrón de ruta cuantificado con varios tipos de aristas). Si los metadatos formalizados son importantes para tu caso de uso, puedes usar vistas para realizar la transición de un gráfico sin esquema a un esquema con tipos. También puedes optar por usar un gráfico sin esquema para algunos casos de uso y un gráfico de esquema con tipos para otros. Para obtener más información, consulta Elige un diseño de esquema basado en consultas de grafos.

En el siguiente ejemplo, se muestra el flujo de trabajo para realizar la transición de un gráfico sin esquema a un gráfico formalizado en cuatro pasos:

  1. Define las tablas canónicas GraphNode y GraphEdge para el modelo sin esquema.

  2. Crea un gráfico inicial y flexible en esas tablas sin esquema.

  3. Define vistas con tipo (Person, Company, WorksFor) que extraen y formalizan los datos de las tablas sin esquema.

  4. Crea el gráfico final con escritura segura que usa estas vistas como tablas de nodos y aristas.

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

¿Qué sigue?