本文へスキップ
BecomeCoder

Neo4jコース · 第6章 集計と高度なクエリ · レッスン34

レコメンドを書く ― 「共演者の共演者」でおすすめ俳優

ローカル実施

導入

この章の総合演習として、これまで学んだ MATCHWHEREWITH・集約関数を組み合わせ、実際に使われる「レコメンド」の考え方をCypherで書いてみましょう。

説明

やりたいことは「ある俳優(Aliceとします)とまだ共演したことのない、共演者の共演者」を、共演した回数が多い順におすすめとして提示することです。SNSの「知り合いかも」やECサイトの「あなたへのおすすめ」と同じ発想です。

graph LR
    me["Alice<br/>(自分)"] -- ACTED_IN --> m1["共演した映画"]
    m1 -- ACTED_IN --> co["共演者"]
    co -- ACTED_IN --> m2["共演者の別の映画"]
    m2 -- ACTED_IN --> cand["おすすめ候補<br/>(まだ共演していない)"]

これをCypherで組み立てると、次のようになります。

MATCH (me:Person {name: 'Alice'})-[:ACTED_IN]->(:Movie)<-[:ACTED_IN]-(co:Person)
MATCH (co)-[:ACTED_IN]->(:Movie)<-[:ACTED_IN]-(candidate:Person)
WHERE candidate <> me
  AND NOT (me)-[:ACTED_IN]->(:Movie)<-[:ACTED_IN]-(candidate)
WITH candidate, count(*) AS strength
RETURN candidate.name AS recommendedActor, strength
ORDER BY strength DESC
LIMIT 5

このクエリを段階ごとに読み解いてみましょう。

  1. 1つ目の MATCHAlice が出演した映画に、他に誰が出演していたか(co = 共演者)を探す。
  2. 2つ目の MATCH … その共演者 co が、さらに他の映画で誰と共演していたか(candidate = 候補)を探す。
  3. WHERE candidate <> me … 候補が自分自身でないことを確認する。
  4. WHERE NOT (...)NOT と丸括弧内のパターンを組み合わせることで「候補とAliceがまだ共演していない」ことを条件にする(パターンの否定という、Cypherならではの書き方)。
  5. WITH candidate, count(*) AS strength … 候補ごとに、何本の映画を通じてこの経路に現れたか(=共演者を介したつながりの強さ)を数える。
  6. 最後に、そのつながりの強さが強い順に並べ、上位5件だけをおすすめとして返す。

このように、グラフデータベースにおける「レコメンド」は、特別な機械学習を使わなくても、つながりのパターンをたどって数えるだけで、それなりに実用的な結果を作れます。第1章で紹介した「レコメンド」のユースケースが、ここまで学んだ機能の組み合わせだけで実現できることを体感できたはずです。

次章では、視点を変えて「そもそもグラフとしてどうデータをモデリングするか」という設計の考え方を学びます。