Tutorial: Data Modeling Home MDM

本記事では、家庭でデバイス管理を行うグラフネットワークを、実際にデータモデリングしていきましょう。Neo4j Aura 及び Cypher を利用します。

課題

デジタル化の推進により、家庭でも一人複数台のデバイスを持つことが当たり前になってきました。

一人一台以上のスマホを持ち、作業用のパソコンと自宅用には携帯タブレット。右手にはウェアラブルデバイスを装着し、居間にはテレビ用にパソコンも備え、他にもホームデバイスやゲーム機など、家庭に置かれるデバイス機器は増えていく一方でしょう。

一家庭が所有する個人デバイスを管理できるアプリケーションを作成し、OS の更新作業やメンテナンス、アカウントの利用状況などを可視化したいというニーズが出てきたと仮定します。

そこで、解決策として、簡単なモバイルデバイス管理システム (Mobile Device Managemnt System, MDM) を表現するグラフネットワークを作成してみましょう。

Alice ユーザー

Alice は、iPhone 13 と Macbook Pro 16 inch を所有しているとします。まずはユーザーを表す User ノードと、デバイスを表す Device ノードを、所有するという意味での [:OWNS] リレーションを用いて作成してみましょう。

CREATE (u:User {name: 'alice'}),
    (u)-[:OWNS]->(d1:Device:Asset:Mobile {id: 1, name: 'iPhone 13'}),
    (u)-[:OWNS]->(d2:Device:Asset:Computer {id: 2, name: 'Macbook Pro 16 inch'});

この時、デバイスのモデリングについて一つポイントが有ります。Device という汎用的なラベルだけを持つ形にして、プロパティで Device {type: 'iPhone'} のようにデバイスの種類を表現することも可能です。

しかし、ユースケースの一つとして、「家庭で所有する全ての iPhone をリストしたい」といったクエリを発行したいことは容易に想像できます。その場合、プロパティでデバイスの種類を表現するより、複数のラベルでデバイスの種類を表現しておくほうが、効率的なクエリを実行できます。

また、全てのデバイスに Device というラベルをもれなく付与しておくことで、「家庭で所有する全てのデバイスをリストしたい」という要求にも答えることができます。

Bob ユーザーの追加

Bob も同様に以下のデバイスを所有しているようです。すでに作成したグラフネットワークにデータセットを追加してみましょう。

CREATE (u:User {name: 'bob'}),
    (u)-[:OWNS]->(d1:Device:Asset:Mobile {id: 3, name: 'iPhone 10'}),
    (u)-[:OWNS]->(d2:Device:Asset:Computer {id: 4, name: 'Macbook Air 13 inch'}),
    (u)-[:OWNS]->(d3:Device:Asset:Computer {id: 5, name: 'Macbook Pro 16 inch'}),
    (u)-[:OWNS]->(d4:Device:Asset:Smartwatch {id: 6, name: 'Apple Watch Series 7'});

ところで、Alice と Bob の関係性についても定義してみましょう。二人は親子のようです。ユーザー間のリレーションも以下のように定義しておきましょう。

MATCH (a:User), (b:User)
WHERE a.name = 'alice' AND b.name = 'bob'
CREATE (a)-[PARENTS_OF]->(b), (b)-[:CHILD_OF]->(a)

現時点でのグラフネットワーク (1st Iteration)

この段階で、グラフネットワークは以下の様になっているはずです。

First Iteration

例えば、家庭で所有する全ての Mobile を取得したい場合、以下の Cypher クエリを実行します。

MATCH (m:Mobile) RETURN m.id, m.name

また、例えば Bob が所有する全ての Computer を取得したい場合、以下の Cypher クエリを実行します。

MATCH (u:User)-[:OWNS]->(c:Computer)
WHERE u.name = 'bob'
RETURN u.name, c.id, c.name

製品ラベル (Product)

ここで、製品ごとにデバイスを管理したい要件が出てきました。例えば、iPhone であれば現在どのモデルを誰が持っているのか、を知りたいケースです。

今回は、後から Product ノードを製品ごとに作成し、既存の Device ノードと紐づけてみましょう。

Macbook

CREATE (p:Product {name: 'Macbook'});

MATCH (p:Product), (d:Device)
WHERE p.name = 'Macbook' AND d.name IN ['Macbook Air 13 inch', 'Macbook Pro 16 inch']
CREATE (d)-[:PRODUCTS_OF]->(p);

iPhone

CREATE (p:Product {name: 'iPhone'});

MATCH (p:Product), (d:Device)
WHERE p.name = 'iPhone' AND d.name IN ['iPhone 13', 'iPhone 10']
CREATE (d)-[:PRODUCTS_OF]->(p);

Apple Watch

CREATE (p:Product {name: 'Apple Watch'});

MATCH (p:Product), (d:Device)
WHERE p.name = 'Apple Watch' AND d.name IN ['Apple Watch Series 7']
CREATE (d)-[:PRODUCTS_OF]->(p);

現時点でのグラフネットワーク (2nd Iteration)

この時点で、グラフネットワークは以下の様になっているはずです。

Second Iteration

例えば、「Alice が持っている iPhone 製品全て」をグラフで知りたい場合、以下の Cypher クエリが利用できます。

MATCH (u:User)-[:OWNS]->(d:Device)-[:PRODUCTS_OF]->(p:Product)
WHERE p.name = 'iPhone' AND u.name = 'alice'
RETURN d, p, u

会社の追加

ここで、Apple という会社が出しているデバイス一覧についてデータをクエリしたいケースが出てきたと考えてみましょう。

その場合、新しく Company ノードを作成し、Product ノードに :PRODUCES リレーションを追加することで表現できます。

CREATE (c:Company {name: 'Apple Inc.'});

MATCH (p:Product), (c:Company)
WHERE c.name = 'Apple Inc.' AND p.name in ['Macbook', 'iPhone', 'Apple Watch']
CREATE (c)-[:PRODUCES]->(p);

例えば、「Apple Inc. が生産している全てのデバイス一覧をユーザー名と共に表示させる」クエリは、以下のように表現できます。

MATCH (u:User)-[:OWNS]->(d:Device)-[:PRODUCTS_OF]->(p:Product)<-[:PRODUCES]-(c:Company)
WHERE c.name = 'Apple Inc.'
RETURN u.name, d.name, p.name

最終的に、グラフネットワークは以下の様になっていることでしょう。

Third Iteration

最後に

以上、家庭でデバイス管理を行う MDM を具体例に、データモデリングの手法と Cypher について簡単に紹介しました。

色々なパターンのデータモデリングを経験することは、グラフデータベースならではのモデリング手法を学んでいく優れた手法の一つでしょう。

Neo4j グラフデータベースはスキーマレスであり、後から要件を追加していく場合でも、既存の関連に破壊的変更を加えることなくデータセットを容易に追加していけます。

今回紹介したグラフネットワークに、自分なりの要件を追加してデータモデリングの試行錯誤をしてみてはいかがでしょうか。

2021-09-29