Trabalhar com medidas

Este documento mostra como definir e consultar medidas nos gráficos. É possível usar medidas para garantir que as agregações sejam realizadas corretamente nas junções.

Visão geral

Uma medida é uma propriedade agregada definida na cláusula PROPERTIES de uma tabela de nós ou de bordas. As medidas são definidas usando a palavra-chave MEASURE e uma das seguintes funções de agregação compatíveis:

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

As medidas definem a agregação em referência à KEY da tabela de nós ou de bordas em que estão definidas. Isso significa que, ao consultar uma medida, a agregação é realizada corretamente, mesmo que a tabela subjacente seja unida de uma forma que cause a duplicação de linhas.

Não é possível referenciar uma propriedade definida por uma medida em uma consulta GQL. Em vez disso, acesse as medidas chamando a TVF GRAPH_EXPAND para criar uma representação de tabela nivelada do gráfico. Essa função não aceita todos os tipos de gráficos. Para mais informações sobre quais gráficos formam uma entrada válida, consulte as limitações de entrada.

É possível chamar a função AGG na saída da GRAPH_EXPAND TVF para agregar as propriedades de acordo com a função de agregação definida na medida.

Definir medidas

Defina as medidas na PROPERTIES cláusula de uma definição de tabela de nós ou de bordas usando a MEASURE() palavra-chave em torno de uma função de agregação compatível.

O exemplo a seguir cria um conjunto de dados chamado university e tabelas para faculdades, departamentos e cursos:

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

A instrução a seguir cria um gráfico chamado SchoolGraph que define medidas em algumas das propriedades dos nós Department e Course. É necessário fornecer um alias para as propriedades definidas por uma medida.

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

Uma visualização do gráfico SchoolGraph.

A medida total_budget é definida como MEASURE(SUM(budget)). A medida bloqueia a agregação para a KEY, que é dept_id.

Entender a contagem excessiva

Ao unir tabelas, os dados são repetidos sempre que há uma relação um-para-muitos nos dados. Por exemplo, se você unir as tabelas Course, Department e College, um departamento com vários cursos vai aparecer em várias linhas na saída:

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 você tentar calcular o orçamento total por faculdade usando SUM(budget), o orçamento do departamento de Ciência da Computação será contado duas vezes. É possível evitar esse problema consultando a tabela Department diretamente, mas essa abordagem não funciona se você quiser calcular várias agregações de tabelas diferentes que contribuem para os dados unidos. A seção a seguir mostra como as medidas resolvem esse problema.

Consultar um gráfico com medidas

É possível consultar um gráfico com medidas usando a GQL, mas a consulta não pode referenciar diretamente nenhuma propriedade definida por uma medida. Por exemplo, a consulta a seguir referencia nós que têm propriedades de medida definidas, mas não usa nem retorna nenhum dos campos de medida:

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    |
 +------------------------+------------------------+-----------------*/

Trabalhar com medidas

Para trabalhar com medidas, use a GRAPH_EXPAND função com valor de tabela (TVF) para consultar o gráfico como uma única tabela nivelada. As colunas na tabela de saída são derivadas das propriedades definidas no gráfico para cada tabela de nós e de bordas. Para evitar conflitos de nomenclatura, as colunas são nomeadas concatenando o rótulo da tabela de nós ou de bordas e o nome da propriedade. Por exemplo, Course_course_name ou Department_total_budget. A consulta a seguir mostra alguns exemplos de saída da 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       |
 +------------------------+------------------------+-------------------+--------------------+

A função GRAPH_EXPAND produz a tabela nivelada aplicando uma série de operações LEFT JOIN a tabelas de nós e de bordas. Um gráfico de entrada válido precisa ter exatamente uma tabela de nós raiz, que é uma tabela cujo KEY valor não aparece em nenhuma outra tabela. Os dados que não podem ser acessados na tabela de nós raiz por uma série de junções não aparecem na saída. No exemplo anterior, a tabela Course é a tabela de nós raiz. O departamento Research é omitido da saída porque não tem cursos.

Não é possível selecionar diretamente uma coluna para uma propriedade definida por uma medida. Em vez disso, é necessário envolvê-las na AGG() função. Essa função garante que a agregação definida nas medidas seja realizada exatamente uma vez por chave.

A consulta a seguir calcula simultaneamente o orçamento total e o número total de cursos de cada faculdade:

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             |
 +------------------------+----------------+---------------*/

Conferir o esquema GRAPH_EXPAND

Para conferir o esquema da tabela retornada pela GRAPH_EXPAND função sem chamar a função, use o BQ.SHOW_GRAPH_EXPAND_SCHEMA procedimento do sistema:

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

Esse procedimento preenche a variável schema com o nome, o tipo e o modo de cada coluna. Ele também indica se a propriedade referenciada pela coluna é uma medida e lista qualquer descrição ou sinônimos definidos nela.

A seguir