5facebook0twittertはてぶ0ここまで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つのステップがクリアできればパーフェクトな解決策と言えるでしょう。[問題解決ためのトライ&エラーフロー]M04さんのケースここでM04さんのプロファイルを思い出してみましょう。話すタイプこれから、M04さんのリクエストプロファイル及び必須条件をもとに、「問題解決フロー」に従って実現可能性を検討してみます。必須条件ではないリクエストアウトドア(Outdoor):海、川このようなリクエストは、単純にすべての要素をサブグラフにすることにしました。性格(Personality):気にしない「気にしない」というリクエストは「どれでもいい」という意味で捉え、"性格"に含まれるすべての属性(ここでは”内向的”と”外向的”)をサブグラフにします。必須条件が存在するリクエスト教育(Education):短大・高専以上(必須)このようなリクエストは、まずリクエストとして挙がっている要素のみをサブグラフにします。"大学院"]のようなパターンとして簡単に把握することができます。ここで、M04さんの場合、教育を必須条件として範囲を決めているので、対象外の学歴を持つ候補者は、除外する必要があります。そのフィルター条件をサブグラフにすると、以下のようになります。"各種専門学校"]のようなパターンとして利用することができます。上記のような2つのパターンが必要なのでしょうか。実際にシミュレーションしてみます。"義務教育"]をフィルターすると、教育の要素はマッチしなくても、他にマッチする要素が存在するためにマッチする要素と共に「◎◎さん」も残ることになります。これは望んでいない結果です。result◎◎さん["水泳"]今回の処理で望んでいる結果は、M04さんの教育に対するリクエストと一致する要素が存在しない場合、「◎◎さん」を候補者から除外することです。このような処理は、以下のようにフィルター条件を付けると、「◎◎さん」のオリジナルプロファイル(list)のなかから、必須要素のフィルター条件が1個でも含まれている場合、「◎◎さん」が除外されます。次のCypherクエリーは、ここまでの説明をフルに反映した例です。グラフデータベースNeo4j』には、上記のようなパターン処理に対する詳細な解説を入れています。ご興味がありましたらあわせてこちらもご参照ください。前項の「ここまでの問題点のおさらいとデータモデル改善の方向性」を参照して頂きたいのですが、「パターンマッチの結果値のカラム名の特定が困難」という問題点がありました。以下のリストを見て下さい。結果値の要素の数が多い場合や曖昧な言葉が存在する場合、意味が正しく伝わらない可能性があります。次のリストの「とちらでも良い」という要素は、「会話のタイプ」であり、「信じる」という要素は「占い」に関することです。4ここでは、2つのことを考えてみました。案1以下のように要素の内容でタイトルが要らないようにすることです。今回の場合は、身長や収入などの数字が含まれているので、混乱を完全に避けることは難しいように見えます。例のように140という数字が登場した場合、身長なのか収入なのか混乱を招く可能性が高いです。140]案2もう一つは、タイトル用のサブドメインをデータモデルに反映することです。タイトル出力専用のサブドメインが存在し、すべての要素とタイトルがノードの属性として存在している場合、Cypherクエリーを利用してタイトルを逆引きすることが可能です。以下のようなCypherクエリーを使います。x)として渡すことができます。必須要素のフィルター条件を人のノードの属性に持たせる方法も考えられます。簡単な例で考え方を説明します。"各種専門学校"]のような必須要素のフィルター条件を人の属性として格納しておいて、Cypherクエリーの条件として使う方法です。次のように必須要素のフィルター条件を属性として格納します。man.filter_education="義務教育|高等学校|各種専門学校"この要素は、以下のようにリストに変換し、WITHやWHERE、RETURNで利用することができます。各種専門学校]このリストは、必須要素のフィルター条件として利用することができます。)・・・しかし、この方式には落とし穴があります。どのサブドメインが必須なのかを知っている必要があります。事前に知らない場合、どの属性が対象になるか分からないためにCypherクエリーで無条件に20種の属性を並べて処理することになります。・・・さらに、20種のすべてのリストをWHEREに並べてフィルターを行うことになります。これはやりたくないですね。居住地域のようにあらかじめ必須条件やフィルター条件がかならず発生すると事前に分かっているサブドメインについて適用するのはどうでしょうか。都道府県のようなフィルター条件をグラフにした場合、圧倒的にフィルター条件のパターンのほうが多くなります。次は、今回のM04さんのリクエストで居住地域の必須要素のサブグラフです。次は、必須要素のフィルター条件のグラフです。今回は、特別に居住地域のフィルター条件だけは、人の属性として持たせてみることにします。前項の「M04さんのリクエストの解決策を考えてみる」でデータモデルを改善するための様々な方策を検討しました。ここでは、検討した内容に基づいてデータモデルの変更に入ります。コンセプトデータモデル今回のデータモデルの変更は、既存データモデルにリクエストプロファイルのために20種(Category2)のサブドメインを追加し、さらに必須要素のフィルター条件のために19種(Category3)のサブドメインを追加することにしました。居住地域のみは、人の属性として持たせています。FI:Filterディテールデータモデル以下は、上記のコンセプトデータモデルに基づいてそれぞれのサブドメインを並べたディテールデータモデルです。最初から、こちらを書いても大差がないのではないかと思う方がいらっしゃるかも知れません。今回の場合は、実際に進めてみると、コンセプトデータモデルでサブドメインをどのようにするか仮説を立て、簡単なプロトタイプを作って実現の可能性を検討してから、ディテールデータモデルを確定することが出来ました。以下は、データモデルに基づいたドメインモデルの詳細です。これで、今回のグラフのラベル名、タイプ、関係性などをすべて確定しました。フィルター条件のグラフ化などの問題点をすべて盛り込んだデータモデル設計を完了しました。次回では、改善したデータモデルで再度M04さんの婚活候補者を探してみたいと思います。お楽しみに!AuthorleefacebookTwitterデータベースが大好きなサーバサイドのエンジニア。Neo4j、MongoDBのテクニカルサポート、IoTビックデータ処理基盤のアーキテクトとして活動しています。LABの情報を逃さずチェックしよう!メールアドレスを登録すると記事が投稿されるとメールで通知します。※登録後メールに記載しているリンクをクリックして認証してください。#28に、弊社エンジニア細見・李が登壇します。#21)に、弊社エンジニア李が登壇します。LABの情報を逃さずチェックしよう!メールアドレスを登録すると記事が投稿されるとメールで通知します。※登録後メールに記載しているリンクをクリックして認証してください。