measure を操作する
このドキュメントでは、グラフで measure を定義してクエリする方法について説明します。 measure を使用すると、結合全体で集計が正しく行われるようにできます。
概要
measure は、ノードテーブルまたはエッジテーブルの PROPERTIES 句内で定義される集計プロパティです。 measure
は、MEASURE キーワードと、次のいずれかのサポートされている集計関数を使用して定義されます。
SUMAVGCOUNTCOUNT(DISTINCT)MINMAX
measure は、定義されているノードテーブルまたはエッジテーブルの KEY を参照して集計を定義します。つまり、measure
をクエリすると、基盤となるテーブルが重複する行を引き起こす方法で結合されている場合でも、集計が正しく行われます。
GQL クエリで measure によって定義されたプロパティを参照することはできません。代わりに、
グラフのフラット化されたテーブル表現を作成するために、
GRAPH_EXPAND TVF
を呼び出すことで、measure にアクセスします。この関数は、すべてのタイプのグラフを受け入れるわけではありません。有効な入力となるグラフの詳細については、入力の制限をご覧ください。
GRAPH_EXPAND TVF の出力に対して AGG 関数を呼び出して、measure で定義した集計関数に従ってプロパティを集計できます。
measure を定義する
measure は、サポートされている集計関数を MEASURE() キーワードで囲むことで、ノードテーブルまたはエッジテーブル定義の
PROPERTIES 句
内で定義します。
次の例では、university という名前のデータセットと、大学、学部、コースのテーブルを作成します。
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);
次のステートメントは、Department ノードと Course ノードの一部のプロパティで measure を定義する SchoolGraph というグラフを作成します。
measure によって定義されたプロパティにはエイリアスを指定する必要があります。
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)
);

total_budget measure は MEASURE(SUM(budget)) として定義されます。この measure は、集計を KEY(dept_id)にロックします。
重複カウントについて
テーブルを結合すると、データに 1 対多の関係があるたびにデータが繰り返されます。たとえば、Course、Department、College テーブルを結合すると、複数のコースがある学部が出力で複数の行に表示されます。
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 |
+------------------------+------------------------+-----------------+----------*/
SUM(budget) を使用して大学ごとの合計予算を計算しようとすると、コンピュータ サイエンス学部の予算が 2 回カウントされます。この問題を回避するには、Department
テーブルを直接クエリしますが、この方法では、結合されたデータに寄与する異なるテーブルから複数の集計を計算する場合に機能しません。次のセクションでは、measure
でこの問題を解決する方法について説明します。
measure を使用してグラフをクエリする
GQL を使用して measure を含むグラフをクエリできますが、クエリで measure によって定義されたプロパティを直接参照することはできません。たとえば、次のクエリは、measure プロパティが定義されているノードを参照しますが、measure フィールドを使用または返しません。
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 |
+------------------------+------------------------+-----------------*/
measure を操作する
measure を操作するには、
GRAPH_EXPAND
テーブル値関数(TVF)
を使用して、グラフを 1 つのフラット化されたテーブルとしてクエリします。
出力テーブルの列は、各ノードテーブルとエッジテーブルのグラフで定義されたプロパティから派生します。名前の競合を防ぐため、列にはノードテーブルまたはエッジテーブルのラベルとプロパティ名を連結した名前が付けられます(例:
Course_course_name、Department_total_budget)。次のクエリは、GRAPH_EXPAND
TVF からの出力例を示しています。
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 |
+------------------------+------------------------+-------------------+--------------------+
GRAPH_EXPAND 関数は、一連の LEFT JOIN
オペレーションをノードテーブルとエッジテーブルに適用して、フラット化されたテーブルを生成します。有効な入力グラフには、
ルートノードテーブルが 1 つだけ必要です。これは、KEY値が他のテーブルに表示されないテーブルです。
一連の結合を介してルートノードテーブルから到達できないデータは出力に表示されません。前の例では、Course
テーブルがルートノードテーブルです。Research 学部にはコースがないため、出力から除外されます。
measure によって定義されたプロパティの列を直接選択することはできません。
代わりに、
AGG()関数でラップする必要があります。
この関数により、measure で定義された集計がキーごとに 1 回だけ実行されます。
次のクエリは、各大学の合計予算とコースの合計数を同時に計算します。
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 |
+------------------------+----------------+---------------*/
ベスト プラクティス
measure を使用してグラフを設計する場合は、次のベスト プラクティスに従ってください。
単一テーブル内でノードとエッジを定義する
ノードテーブル定義とその接続エッジテーブル定義には、同じテーブルを使用することをおすすめします。テーブルを再利用すると、ノードテーブルとエッジテーブルの間に正確な 1 対 1(1:1)の関係が確保され、ファンアウトを防ぎ、GRAPH_EXPAND
関数があいまいなエッジを無視しないようにします。
たとえば、Student テーブルと Course テーブルを参照する外部キーを含む入力テーブル Enrollment がある場合は、Enrollment
入力テーブルを使用して Enrollment ノードとその出力エッジを定義します。
多対多の関係をノードテーブルとしてモデル化する
多対多(M:N)の関係は、テーブル A の行がテーブル B の複数の行に対応し、テーブル B の行がテーブル A
の複数の行に対応する場合に発生します。 たとえば、1 人の生徒が複数のコースに登録でき、1 つのコースに複数の生徒が参加できます。中間結合テーブルを使用すると、多対多の関係を 2 つの 1 対多の関係に分離できます。
たとえば、Student テーブルと Course テーブルを参照する外部キーを含む Enrollment
テーブルを定義できます。CREATE PROPERTY GRAPH ステートメントで 2
つのディメンション ノードテーブルを接続するエッジテーブルとして中間結合テーブルをモデル化すると、これらのエッジの関係があいまいであるため(多対 1
または 1 対 1 が明確でないため)、GRAPH_EXPAND 関数はこれらのエッジを無視します。
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)
);
GRAPH_EXPAND 関数は、これらのエッジがあいまいであるため(ノードテーブル自体が多対 1 または 1 対 1
が明確でないため)無視します。グラフ内のすべてのエッジが無視されると、GRAPH_EXPAND または BQ.SHOW_GRAPH_EXPAND_SCHEMA の呼び出しがエラーで失敗します。
measure の M:N 関係を正しくモデル化するには、中間結合テーブルをノードテーブルに昇格させます。この構造では、結合ノードテーブルは単一のルートノードテーブル(入次数が 0 のノードテーブル)として機能します。次に、結合テーブルを共有して N:1 を各ディメンション ノードテーブルに接続する 2 つの多対 1(N:1)エッジテーブルを定義します。
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)
);
この構造では、Enrollment は、N:1 を Student ディメンション テーブルと Course ディメンション
テーブル(入次数 1)に接続する単一のルートノードテーブル(入次数 0)として機能します。GRAPH_EXPAND
関数は、Enrollment から Student と Course
に外向きにトラバースすることで、このグラフをフラット化できます。これらのテーブルのいずれかに measure を定義すると、measure
列に対して AGG 関数を呼び出して、重複カウントなしで集計を正しく計算できます。
GRAPH_EXPAND スキーマを表示する
GRAPH_EXPAND 関数を呼び出さずに、この関数から返されるテーブルのスキーマを表示するには、BQ.SHOW_GRAPH_EXPAND_SCHEMA システム プロシージャを使用します。
DECLARE schema STRING DEFAULT '';
CALL BQ.SHOW_GRAPH_EXPAND_SCHEMA('university.SchoolGraph', schema);
SELECT schema;
このプロシージャは、各列の名前、型、モードを schema
変数に入力します。また、列で参照されるプロパティが measure かどうかを示し、定義した説明やシノニムを一覧表示します。
次のステップ
- プロパティ グラフを作成してクエリする方法を学習する 。
- グラフ スキーマについて学習する。