fbpx

CL LAB

HOME > Blog > lee > 婚活支援プロジェクト(3/4): どのように改善したらいいのか #neo4j

婚活支援プロジェクト(3/4): どのように改善したらいいのか #neo4j

 ★ 5

ここまで2回に渡って「婚活支援」というトライアルプロジェクトを進めながら記事を書いてきましたが、その過程でいくつかの問題点を挙げています。今回は、その問題点をどのように改善したらいいのかを考え、少なくともデータモデルにまでは落として行きたいと思います。

第1回目:構想からデータモデル設計まで
第2回目:データ処理と問題点
第3回目:どのように改善したらいいのか
第4回目:改善したデータモデルによるデータ処理

ここまでの問題点のおさらいとデータモデル改善の方向性

ここでは、前回までのトライアルプロジェクトを進めながら出てきた問題点をおさらいし、改善の方向性を出していきたいと思います。

問題1

婚活をする男女にオリジナルプロファイルとリクエストプロファイルがありますが、リクエストプロファイルはデータモデルに反映されていません。

問題1の改善案

リクエストプロファイルをデータモデルに取り込む

問題2

プロファイル内のいくつかの要素は必須条件になることがあります。例えば身長や収入、住んでる場所などを限定した場合です。

問題2の改善案

この問題もデータモデルに取り込んで解決する方法を探ってみることにしました。

問題3

ある要素は重み付けをして優先度を高くしたいというようなケースがあります。例えば年収の高い相手は優先度を高くする、などのケースが想定できます。

問題3の改善案

この問題には取り組まないことにします。理由は以下のとおりです。
この問題は、基本的に優先度が高い要素を持った候補者の表示ランクを上げたいということが背景にあります。既に優先度が高い要素は必須条件としているような状態なので、今回、さらに定量的な重み付けをすることによる有意差は出ないと考えました。

問題4

人の様々なパーソナリティを表す言葉に重複や曖昧な表現が存在すると、表示ランクに影響があったり、意味が伝わりにくくなります。例えば、「その他」、「どちらでもよい」、「どちらでもない」のような言葉です。

問題4の改善案

この問題は、データ処理の方法とは直接関係しないということで、属性値(要素)の変更までは踏み切らないことにしました。現実の世界であれば、プロファイル作成のための調査資料にまでさかのぼる必要があります。

問題5

ある種類のサブドメインの要素数が非常に多い場合、グループを表す言葉を検討すべきかもしれません。例えば、スポーツの場合は、全種目の名称を並べるより、種目自体(例えば球技など)を要素にしたほうが良いかもしれません。

問題5の改善案

この問題は、データ処理の方法とは直接関係しないということで、属性値(要素)の変更までは踏み切らないことにしました。
ただし、現実のケースでは上記で述べたような「サブドメインのグループ化」は頻繁に行われると思います。実際、サブドメインのグループ化(ネスト化)はグラフデータの利点でもあります。ただし、今回のプロジェクトはあくまで理想の相手を発見するというプロセスに集中するため、付随的な要素は除外するようにしました。

問題6

パターンマッチの結果値のカラム名の特定が困難。

問題6の改善案

この問題は、データ処理とは直接関係なく、処理結果を出力するときの可視化の問題なので、データモデルには反映せず、処理方法を考えてみたいと思います。

前回のデータモデルをシステム化した場合

前回の記事では、リクエストプロファイルや必須条件の問題を直接Cypherクエリーの調整で対応しました。もし、そのままの状態でシステムを開発すると、Neo4jの外部にリクエストプロファイルや必須条件を保存しておいて、クエリーを発行する時にアプリケーションで情報を検索し、Cypherクエリーを生成して実行することになります。
そのようにするためには、外部のデータベースに候補者の個人情報を含めてNeo4jのリクエストや必須条件の要素を格納して置くことが考えられます。この案は、既に外部のデータベースを運用しているようなケースでは、とても身近な選択肢の一つなのかも知れません。但し、Neo4jでシンプルに実現できることに対して安易な選択をすれば、それはシステムを複雑にするなど非効率(コスト増)に繋がりかねません。

今回のトライアルプロジェクトは、基本方針だけを決めて進めています。開始段階で情報収集や大まかな分析のシナリオを作成し、データモデルを検討はしていますが、この段階で問題点として挙がっていることに対する具体的な解決策までは考えていませんでした。いわゆる走りながら考えているという状態です。私は、「Cypherクエリーの論理構成能力は、SQLよりはるかに高いです」と言い続けて来ましたが、今回は、それを立証しなければいけない状況になりました(汗)。以下は私の苦闘の記録と言ってもいいかもしれませんね。

M04さんのリクエストの解決策を考えてみる

問題解決のためのトライ&エラーフロー

Neo4jは、このようなタイプの問題解決のために「トライ&エラー」で最適な解を求めていくことに適しています。なぜかというと、問題をグラフにして、それをNeo4jにロードし、Cypherクエリーで狙い通りのデータが取得できるかどうか試してみるまでのサイクルが、とても短い時間で簡単に実行できるからです。
今回は、M04さんのリクエストに対して1つずつ解決策を考えてみることにしました。ここで試してみたことは、以下のような「問題解決のためのトライ&エラーフロー」です。簡単に言うと、最終的に狙い通りの結果とパフォーマンス、スマートなCypherクエリーという3つのステップがクリアできればパーフェクトな解決策と言えるでしょう。

solution-flow

[問題解決ためのトライ&エラーフロー]

M04さんのケース

ここでM04さんのプロファイルを思い出してみましょう。以下の表です。

カテゴリ オリジナル リクエスト 必須
Alcohol 飲む 飲む
Born 1986 1981-1989
Education 大学 短大以上
Fortunetelling 信じない 信じない
Healthcare 意識して運動する 意識して運動する
Height 190 140-160
Holiday 土日祝日 土日祝日
Income 700 気にしない
Indoor TV感想 映画感想,ゲーム
Job 会社員 無職,学生,家事手伝は駄目
Karaoke 好き 好き
Location 埼玉県 埼玉県,千葉県,東京都,神奈川県
Maritalhistory 無し 無し
Meeting 積極的 積極的
Outdoor 公園 海,川
Personality 外向的 気にしない
Pet 猫派 猫派
Smoking 吸わない 吸わない
Sport バスケットボール 気にしない
Talk 聞くタイプ 話すタイプ

 

これから、M04さんのリクエストプロファイル及び必須条件をもとに、「問題解決フロー」に従って実現可能性を検討してみます。

必須条件ではないリクエスト

アウトドア(Outdoor):海、川
このようなリクエストは、単純にすべての要素をサブグラフにすることにしました。

indoor

性格(Personality):気にしない
「気にしない」というリクエストは「どれでもいい」という意味で捉え、"性格"に含まれるすべての属性(ここでは”内向的”と”外向的”)をサブグラフにします。

personality

必須条件が存在するリクエスト

教育(Education):短大・高専以上(必須)
このようなリクエストは、まずリクエストとして挙がっている要素のみをサブグラフにします。このようなサブグラフが存在すると、M04さんが相手に求める教育水準に対するリクエストは、["短大・高専", "大学", "大学院"]のようなパターンとして簡単に把握することができます。

education1

ここで、M04さんの場合、教育を必須条件として範囲を決めているので、対象外の学歴を持つ候補者は、除外する必要があります。そのフィルター条件をサブグラフにすると、以下のようになります。これは後に、["義務教育", "高等学校", "各種専門学校"]のようなパターンとして利用することができます。

education2

なぜ、上記のような2つのパターンが必要なのでしょうか。実際にシミュレーションしてみます。例えば、M04さんのリクエスト[(...略,)"野球","サッカー","バレーボール","バスケットボール","テーブルテニス","ヨガ","散歩","ダンス","その他", "短大・高専", "大学", "大学院"]に対して◎◎さんのオリジナルプロファイル[(...略,)"水泳", "義務教育"]をフィルターすると、教育の要素はマッチしなくても、他にマッチする要素が存在するためにマッチする要素と共に「◎◎さん」も残ることになります。これは望んでいない結果です。

・・・
filter ( x IN ["水泳", "短大・高専", "大学", "大学院"] WHERE x IN ["水泳", "義務教育"]) AS result
RETURN woman.name, result
◎◎さん["水泳"]

今回の処理で望んでいる結果は、M04さんの教育に対するリクエストと一致する要素が存在しない場合、「◎◎さん」を候補者から除外することです。
このような処理は、以下のようにフィルター条件を付けると、「◎◎さん」のオリジナルプロファイル(list)のなかから、必須要素のフィルター条件が1個でも含まれている場合、「◎◎さん」が除外されます。

・・・
WHERE NONE ( x IN list WHERE x IN ["義務教育", "高等学校", "各種専門学校"] )
・・・

次のCypherクエリーは、ここまでの説明をフルに反映した例です。

WITH ["飲む",1981,1982,1983,1984,1985,1986,1987,1989,"短大・高専","大学","大学院","信じない","意識して運動する",140,150,160,"土日祝日",100,200,300,400,500,600,700,800,900,"映画感想","ゲーム","公務員","会社員","自営業","企業経営・役員","教師","医師","医療関係","保育士","農林・漁業","パート・アルバイト","学生","家事手伝","好き","埼玉県","千葉県","東京都","神奈川県","無し","積極的","海","川","外向的","内向的","猫派","吸わない","野球","サッカー","バレーボール","バスケットボール","テーブルテニス","ヨガ","散歩","ダンス","話すタイプ"] AS list
MATCH (woman:Person:Woman)-[*]->(things)
WHERE NOT woman-

Author

データベースが大好きなサーバサイドのエンジニア。現代的なデータ基盤のソリューションアーキテクトとして活動しています。

[著書]
グラフデータベースNeo4jの他
https://www.amazon.co.jp/李昌桓/e/B004LWEKOU

leeの記事一覧

CL LAB Mail Magazine

CL LABの情報を逃さずチェックしよう!

メールアドレスを登録すると記事が投稿されるとメールで通知します。

メールアドレス: 登録

※登録後メールに記載しているリンクをクリックして認証してください。

Related post

[無料ウェビナー] GitLab_CI/CDハンズオン_2023111