Utilizzare le misure

Questo documento mostra come definire ed eseguire query sulle misure nei grafici. Puoi utilizzare le misure per assicurarti che le aggregazioni vengano eseguite correttamente nei join.

Panoramica

Una misura è una proprietà aggregata definita all'interno della clausola PROPERTIES di una tabella dei nodi o degli archi. Le misure vengono definite utilizzando la parola chiave MEASURE e una delle seguenti funzioni aggregate supportate:

  • SUM
  • AVG
  • COUNT
  • COUNT(DISTINCT)
  • MIN
  • MAX

Le misure definiscono la loro aggregazione in riferimento a KEY della tabella dei nodi o degli archi su cui sono definite. Ciò significa che quando esegui una query su una misura, l'aggregazione viene eseguita correttamente anche se la tabella sottostante viene unita in modo da duplicare le righe.

Non puoi fare riferimento a una proprietà definita da una metrica in una query GQL. Invece, accedi alle misure chiamando la funzione TVF GRAPH_EXPAND per creare una rappresentazione tabellare piatta del grafico. Questa funzione non accetta tutti i tipi di grafici. Per saperne di più su quali grafici costituiscono un input valido, consulta le limitazioni dell'input.

Puoi chiamare la funzione AGG sull'output della TVF GRAPH_EXPAND per aggregare le proprietà in base alla funzione di aggregazione definita nella misura.

Definisci le misure

Definisci le misure all'interno della clausola PROPERTIES di una definizione di tabella dei nodi o degli archi utilizzando la parola chiave MEASURE() attorno a una funzione di aggregazione supportata.

Il seguente esempio crea un set di dati denominato university e tabelle per college, dipartimenti e corsi:

CREATE SCHEMA IF NOT EXISTS university;

CREATE OR REPLACE TABLE university.College (
  college_id INT64 PRIMARY KEY NOT ENFORCED,
  college_name STRING
);

CREATE OR REPLACE TABLE university.Department (
  dept_id INT64 PRIMARY KEY NOT ENFORCED,
  dept_name STRING,
  college_id INT64,
  budget FLOAT64,
  FOREIGN KEY (college_id) REFERENCES university.College(college_id) NOT ENFORCED
);

CREATE OR REPLACE TABLE university.Course (
  course_id INT64 PRIMARY KEY NOT ENFORCED,
  course_name STRING,
  dept_id INT64,
  credits INT64,
  FOREIGN KEY (dept_id) REFERENCES university.Department(dept_id) NOT ENFORCED
);

INSERT INTO university.College (college_id, college_name)
VALUES (101, 'College of Engineering'),
      (102, 'College of Arts');

INSERT INTO university.Department (dept_id, dept_name, college_id, budget)
VALUES (1001, 'Computer Science', 101, 500000),
      (1002, 'Mechanical Engineering', 101, 400000),
      (1003, 'Fine Arts', 102, 200000),
      (1004, 'Research', 101, 50000);

INSERT INTO university.Course (course_id, course_name, dept_id, credits)
VALUES (1, 'Intro to CS', 1001, 3),
       (2, 'Data Structures', 1001, 4),
       (3, 'Thermodynamics', 1002, 3),
       (4, 'Oil Painting', 1003, 2);

La seguente istruzione crea un grafico denominato SchoolGraph che definisce le misure su alcune delle proprietà nei nodi Department e Course. Devi fornire un alias per le proprietà definite da una misura.

CREATE OR REPLACE PROPERTY GRAPH university.SchoolGraph
  NODE TABLES (
    university.College
      KEY(college_id)
      PROPERTIES(college_id, college_name),
    university.Department
      KEY(dept_id)
      PROPERTIES(dept_id, dept_name, college_id,
        budget OPTIONS(description="Department budget in USD"),
        MEASURE(SUM(budget)) AS total_budget),
    university.Course
      KEY(course_id)
      PROPERTIES(
        course_id,
        course_name,
        credits,
        dept_id,
        MEASURE(AVG(credits)) AS avg_credits,
        MEASURE(SUM(credits)) AS total_credits,
        MEASURE(COUNT(course_id)) AS course_count)
  )
  EDGE TABLES (
    university.Department AS CollegeDept
      SOURCE KEY (college_id) REFERENCES College (college_id)
      DESTINATION KEY (dept_id) REFERENCES Department (dept_id),
    university.Course AS DeptCourse
      SOURCE KEY (dept_id) REFERENCES Department (dept_id)
      DESTINATION KEY (course_id) REFERENCES Course (course_id)
  );

Una visualizzazione del grafico SchoolGraph.

La metrica total_budget è definita come MEASURE(SUM(budget)). La misura blocca l'aggregazione su KEY, ovvero dept_id.

Informazioni sul conteggio eccessivo

Quando unisci le tabelle, i dati vengono ripetuti ogni volta che esiste una relazione uno-a-molti nei dati. Ad esempio, se unisci le tabelle Course, Department e College, un dipartimento con più corsi viene visualizzato in più righe nell'output:

SELECT
  college_name,
  dept_name,
  course_name,
  budget
FROM university.Course
LEFT JOIN university.Department
  ON Course.dept_id = Department.dept_id
LEFT JOIN university.College
  ON Department.college_id = College.college_id;

/*------------------------+------------------------+-----------------+----------+
 | college_name           | dept_name              | course_name     | budget   |
 +------------------------+------------------------+-----------------+----------+
 | College of Engineering | Computer Science       | Intro to CS     | 500000.0 |
 | College of Engineering | Computer Science       | Data Structures | 500000.0 |
 | College of Engineering | Mechanical Engineering | Thermodynamics  | 400000.0 |
 | College of Arts        | Fine Arts              | Oil Painting    | 200000.0 |
 +------------------------+------------------------+-----------------+----------*/

Se provi a calcolare il budget totale per college utilizzando SUM(budget), il budget del dipartimento di informatica viene conteggiato due volte. Puoi evitare questo problema eseguendo query direttamente sulla tabella Department, ma questo approccio non funziona se vuoi calcolare più aggregazioni da tabelle diverse che contribuiscono ai dati uniti. La sezione seguente mostra come le misure risolvono questo problema.

Eseguire una query su un grafico con misure

Puoi eseguire query su un grafico con misure utilizzando GQL, ma la query non può fare riferimento direttamente a qualsiasi proprietà definita da una misura. Ad esempio, la seguente query fa riferimento a nodi con proprietà di misura definite, ma non utilizza né restituisce nessuno dei campi di misura:

GRAPH university.SchoolGraph
MATCH (c:College)-[]-(d:Department)-[]->(course:Course)
RETURN c.college_name, d.dept_name, course.course_name;

/*------------------------+------------------------+-----------------+
 | college_name           | dept_name              | course_name     |
 +------------------------+------------------------+-----------------+
 | College of Engineering | Computer Science       | Intro to CS     |
 | College of Engineering | Computer Science       | Data Structures |
 | College of Engineering | Mechanical Engineering | Thermodynamics  |
 | College of Arts        | Fine Arts              | Oil Painting    |
 +------------------------+------------------------+-----------------*/

Utilizzare le misure

Per lavorare con le misure, utilizza la funzione con valori di tabella (TVF) GRAPH_EXPAND per eseguire query sul grafico come una singola tabella piatta. Le colonne della tabella di output derivano dalle proprietà definite nel grafico per ogni tabella di nodi e archi. Per evitare conflitti di denominazione, le colonne vengono denominate concatenando l'etichetta della tabella dei nodi o degli archi e il nome della proprietà, ad esempio Course_course_name o Department_total_budget. La seguente query mostra alcuni output di esempio della TVF GRAPH_EXPAND:

SELECT
  College_college_name,
  Department_dept_name,
  Department_budget,
  Course_course_name
FROM
  GRAPH_EXPAND("university.SchoolGraph");

/*------------------------+------------------------+-------------------+--------------------+
 | College_college_name   | Department_dept_name   | Department_budget | Course_course_name |
 +------------------------+------------------------+-------------------+--------------------+
 | College of Engineering | Computer Science       | 500000.0          | Intro to CS        |
 | College of Engineering | Computer Science       | 500000.0          | Data Structures    |
 | College of Engineering | Mechanical Engineering | 400000.0          | Thermodynamics     |
 | College of Arts        | Fine Arts              | 200000.0          | Oil Painting       |
 +------------------------+------------------------+-------------------+--------------------+

La funzione GRAPH_EXPAND produce la tabella piatta applicando una serie di operazioni LEFT JOIN alle tabelle dei nodi e degli archi. Un grafico di input valido deve avere esattamente una tabella del nodo radice, ovvero una tabella il cui valore KEY non compare in nessun'altra tabella. I dati non raggiungibili dalla tabella del nodo radice tramite una serie di join non vengono visualizzati nell'output. Nell'esempio precedente, la tabella Course è la tabella del nodo radice. Il reparto Research è omesso dall'output perché non ha corsi.

Non puoi selezionare direttamente una colonna per una proprietà definita da una misura. Devi invece racchiuderli nella funzione AGG(). Questa funzione garantisce che l'aggregazione definita nelle misure venga eseguita esattamente una volta per chiave.

La seguente query calcola simultaneamente il budget totale e il numero totale di corsi per ogni college:

SELECT
  College_college_name,
  AGG(Department_total_budget) AS college_budget,
  AGG(Course_course_count) AS total_courses
FROM
  GRAPH_EXPAND("university.SchoolGraph")
GROUP BY
  College_college_name;

/*------------------------+----------------+---------------+
 | College_college_name   | college_budget | total_courses |
 +------------------------+----------------+---------------+
 | College of Engineering | 900000.0       | 3             |
 | College of Arts        | 200000.0       | 1             |
 +------------------------+----------------+---------------*/

Best practice

Quando progetti un grafico con misure, segui queste best practice:

Definisci nodi e archi all'interno di una singola tabella

Ti consigliamo di utilizzare la stessa tabella per una definizione di tabella dei nodi e per le definizioni delle tabelle degli archi di collegamento. Il riutilizzo della tabella garantisce una relazione esatta uno a uno (1:1) tra la tabella dei nodi e la tabella degli archi, il che impedisce il fan-out e garantisce che la funzione GRAPH_EXPAND non ignori l'arco in quanto ambiguo.

Ad esempio, se hai una tabella di input Enrollment che contiene chiavi esterne che puntano alle tabelle Student e Course, definisci il nodo Enrollment e i relativi archi in uscita utilizzando la tabella di input Enrollment.

Modellare le relazioni many-to-many come tabelle dei nodi

Una relazione molti-a-molti (M:N) si verifica quando una riga della tabella A può corrispondere a più righe della tabella B e una riga della tabella B può corrispondere a più righe della tabella A. Ad esempio, uno studente può iscriversi a più corsi e un corso può avere molti studenti. Puoi separare una relazione many-to-many in due relazioni one-to-many utilizzando una tabella di unione intermedia. Ad esempio, puoi definire una tabella Enrollment che contiene chiavi esterne che puntano alle tabelle Student e Course. Se modelli una tabella di giunzione intermedia come una tabella degli archi che collega due tabelle dei nodi delle dimensioni nell'istruzione CREATE PROPERTY GRAPH, la funzione GRAPH_EXPAND ignora questi archi perché la loro relazione è ambigua: non è chiaramente molti-a-uno o uno-a-uno.

CREATE PROPERTY GRAPH university.SchoolGraph
  NODE TABLES (
    university.Student,
    university.Course
  )
  EDGE TABLES (
    -- Modeling the junction table as a standalone edge causes ambiguity
    university.Enrollment AS StudentEnrollment
      SOURCE KEY (student_id) REFERENCES Student (student_id)
      DESTINATION KEY (course_id) REFERENCES Course (course_id)
  );

La funzione GRAPH_EXPAND ignora questi bordi perché sono ambigui (non chiaramente molti-a-uno o uno-a-uno tra le tabelle dei nodi). Se tutti i bordi di un grafico vengono ignorati, le chiamate a GRAPH_EXPAND o BQ.SHOW_GRAPH_EXPAND_SCHEMA non vanno a buon fine e viene visualizzato un errore.

Per modellare correttamente una relazione M:N per le misure, promuovi la tabella di unione intermedia a una tabella dei nodi. In questa struttura, la tabella dei nodi di giunzione funge da unica tabella dei nodi radice (una tabella dei nodi con un grado interno pari a zero). Quindi, definisci due tabelle arco N:1 che condividono la tabella di unione per connettere N:1 a ciascuna delle tabelle dei nodi delle dimensioni:

CREATE PROPERTY GRAPH university.SchoolGraph
  NODE TABLES (
    university.Student KEY (student_id),
    university.Course KEY (course_id),
    -- Promote the junction table to a node table (acting as the single root node)
    university.Enrollment KEY (enrollment_id)
  )
  EDGE TABLES (
    -- Share (reuse) the Enrollment table to define N:1 edges to each dimension
    university.Enrollment AS EnrollmentToStudent
      SOURCE KEY (enrollment_id) REFERENCES Enrollment (enrollment_id)
      DESTINATION KEY (student_id) REFERENCES Student (student_id),
    university.Enrollment AS EnrollmentToCourse
      SOURCE KEY (enrollment_id) REFERENCES Enrollment (enrollment_id)
      DESTINATION KEY (course_id) REFERENCES Course (course_id)
  );

In questa struttura, Enrollment funge da tabella del nodo radice singolo (grado interno pari a zero) che si connette N:1 alle tabelle delle dimensioni Student e Course (grado interno pari a uno). La funzione GRAPH_EXPAND può appiattire questo grafico spostandosi verso l'esterno da Enrollment a Student e Course. Se definisci misure in una di queste tabelle, puoi chiamare la funzione AGG nelle colonne delle misure per calcolare correttamente le aggregazioni senza conteggi eccessivi.

Visualizza schema GRAPH_EXPAND

Per visualizzare lo schema della tabella restituita dalla funzione GRAPH_EXPAND senza chiamare la funzione, utilizza la procedura di sistema BQ.SHOW_GRAPH_EXPAND_SCHEMA:

DECLARE schema STRING DEFAULT '';
CALL BQ.SHOW_GRAPH_EXPAND_SCHEMA('university.SchoolGraph', schema);
SELECT schema;

Questa procedura compila la variabile schema con il nome, il tipo e la modalità di ogni colonna. Indica inoltre se la proprietà a cui fa riferimento la colonna è una misura ed elenca eventuali descrizioni o sinonimi che hai definito.

Passaggi successivi