こんにちは!開発本部・バックエンドエンジニアのSongです。
2月の下旬に個人ユーザー・フォロワー統合プロジェクトをリリースできました。
このプロジェクトでは以下の機能を提供しています
- ユーザーが自身の操作でFacebookフォロワーアカウントを個人ユーザーアカウントへマイグレーションできる
- ユーザーがFacebook認証で個人ユーザーとして新規登録・ログインできる
- Facebookフォロワーユーザーは新規登録できなくなった。ただし、ログインはできる
最も重要なのはFacebookフォロワーが自身の操作でアカウントを個人ユーザーへマイグレーションできるという機能なので、今回その機能の実装についてお話します。
背景
現在、PR TIMESでは4つのユーザータイプが存在しています
- 企業ユーザー
- メディアユーザー
- 個人ユーザー
- Facebookフォロワー(以下フォロワーと呼ぶ)
各タイプのユーザーには、それぞれの特別な仕様や機能があります。しかし、フォロワーの機能はほぼ個人ユーザーと同じなので、分かれているメリットや明確な理由がありません。具体的には
- フォロワーが提供している機能は企業をフォローすること
- フォローする機能は個人ユーザーにも存在しているため、フォロワーのアカウント情報テーブルとフォローのテーブルをマイグレーションできれば良い
さらに、個人ユーザーアカウントの利便性を向上するために、SNS認証(まずはFacebook)で個人ユーザーとして新規登録・ログイン機能を追加したいのですが、Facebookでログインする機能はフォロワーのログインで利用しているため、個人ユーザーとフォロワーを統合し、個人ユーザーをFacebookでもログインできるようにすることになりました。
最初の段階で、個人ユーザーとフォロワーが統合されるということを事前にフォロワーに告知して、告知期間を経てから、自動的に個人ユーザーにマイグレーションすることにしました。ただし、事前告知期間中にユーザーが自身の操作でマイグレーションすることも可能です。
今回はユーザーが自身の操作でマイグレーションできる機能を中心に説明します。
ユーザーデータを調査した結果
マイグレーションができるように、とりあえずフォロワーと個人ユーザーのデータを調査しました。調査結果は以下のようになりました。
- フォロワーと個人ユーザーのデータが主に2つのテーブルに保存されている。これらのテーブルもユーザータイプによって別の構造や制約を持っている
- アカウント情報
- フォロー中の企業情報(以下フォロー情報と呼ぶ)
- 個人ユーザーのアカウント情報テーブルにはメールアドレスにUNIQUE、NOT NULL制約があり、氏名にNOT NULL制約がある(以下個人ユーザーテーブルの制約と呼ぶ)
- 1つのメールアドレスは企業ユーザー、メディアユーザー、個人ユーザーという3つのユーザータイプにいずれか1つしか登録できない(以下PR TIMESのユーザー制約と呼ぶ)。つまり、企業ユーザー、メディアユーザー、個人ユーザーが同じメールアドレスで存在できない
- フォロワーのアカウント情報テーブルにはメールアドレスや氏名にNOT NULL制約がない。その上、メールアドレスが他のユーザータイプと重複可能であり、メールアドレスや氏名がないフォロワーも存在している
どんな問題が発生したのか?
調査結果に沿って、以下の問題が発生しました。
テーブルの構造や制約が違う問題
フォロワーと個人ユーザーテーブルの構築や制約が違うため、データをそのままマイグレーションすることができません。
情報が重複する・欠ける問題
メールアドレス、氏名が欠けているまたはメールアドレスが企業ユーザー、メディアユーザーと重複されるフォロワーアカウントが個人ユーザーへマイグレーションできません。個人ユーザーテーブルの制約とPR TIMESユーザーの制約に違反するためです。
問題をどのように解決したのか?
では上記の2つの問題をどのように解決したのか?
テーブルの構造や制約が違う問題
フォロワーアカウントを個人ユーザーアカウントへマイグレーションできるように、個人ユーザーのアカウント情報テーブルとフォロー情報テーブルに新しいカラムや制約の追加で解決できました。
まず、フォロワーのアカウント情報テーブルにFacebookのユーザーIDを保存しているカラムがありますが、個人ユーザの方はないため、追加する必要があります。
ALTER TABLE table_name ADD COLUMN fb_user_id VARCHAR(128);
次に、個人ユーザーのフォロー情報テーブルにはPRIMARY制約がありません。しかし、今後マイグレーションを実装するにあたり、PRIMARY制約がないと情報の重複で実装に困る可能性があります。そのため、追加する必要があります。
このテーブルには主にユーザーIDと企業IDを保存するため、2つのカラムを合わせてPRIMARY制約を追加しました。
ALTER TABLE table_name ADD CONSTRAINT table_name_pkey PRIMARY KEY (user_id, company_id);
さらに、フォロー情報テーブルのレコード数が増えてもパフォーマンスの問題が出ないように、これまでなかったcompany_idのINDEXも追加しました。
CREATE INDEX table_name_company_id_idx ON table_name (company_id);
情報が重複する・欠ける問題
調査結果によって、フォロワーを4つのパターンに分けました。
パターン①:メールアドレスが個人ユーザーと重複しているフォロワー
フォロワーアカウントのメールアドレスに該当する個人ユーザーアカウントが既に存在するため、ユーザーがそのままアカウントマイグレーションを実行できます。
その上、マイグレーションする際に個人ユーザーの情報が優先されるため、氏名が欠ける問題も解決できます。
パターン②:メールアドレスまたは氏名がないフォロワー
フォロワーアカウントのメールアドレスまたは氏名がないため、個人ユーザーテーブルの制約に違反してしまいます。
アカウントマイグレーションできるように、ユーザーが情報を追加する必要があります。
パターン③:メールアドレスが企業ユーザーまたはメディアユーザーと重複しているフォロワー
メールアドレスが企業ユーザーまたはメディアユーザーと重複しているため、PR TIMESユーザーの制約に違反してしまいます。
アカウントマイグレーションできるように、ユーザーが別のメールを追加する必要があります。もちろん、もし氏名がないなら追加する必要があります。
パターン④:メールアドレスや氏名があり、メールアドレスが他のユーザータイプと重複していないフォロワー
情報があり、個人ユーザーテーブルの制約とPR TIMESのユーザー制約に違反していないため、ユーザーがそのままアカウントマイグレーションを実行できます。
アカウントマイグレーションの処理
ではマイグレーションを実行する時にどのように処理すれば良いでしょうか?
今回はフォロワーのアカウント情報テーブルとフォロー情報テーブルをマイグレーションする必要があります。上記の4つのパターンがあるので、アカウント移行とアカウント統合という2つの処理に分けました。
アカウント移行
フォロワーアカウントの情報を個人ユーザーアカウントに移行するという処理です。
技術的には個人ユーザーのテーブルに新しいデータをINSERTする処理です。該当の個人ユーザーが存在していないためです。もちろん情報が欠ける場合、移行できるようにユーザーが情報を追加する必要があります。
アカウント移行の対象はユーザーパターン②、③、④です。
アカウント統合
フォロワーアカウントの情報を個人ユーザーアカウントに統合するという処理です。
技術的には、個人ユーザーのテーブルをフォロワーの情報でUPDATEすることです。同じメールアドレスでフォロワーと個人ユーザーに登録したため、統合先が既に存在しています。ですから、INSERTの代わりに、UPDATEで処理します。
ただし、フォロー情報はUPDATEではなくUPSERTで処理します。なぜならフォロワーのフォロー情報を統合する際に、個人ユーザーのフォロー情報テーブルに該当するレコードが存在すればUPDATEで処理するが、存在しなければINSERTで新しいレコードを追加する必要があるからです。
アカウント統合の対象はユーザーパターン①のみです。
フォロワーの管理画面上でアカウント移行・統合を行う
今回のアカウント移行・統合の処理はユーザーの管理画面で行われます。
では、フォロワーがログインした後、そのアカウント移行と統合とどちらが実行できるか?
情報が欠けることをどうやって判定できるか?を考える必要があります。
ログイン中のフォロワーのメールアドレスと氏名を判定することに沿って、以下のように分岐処理で実装しました。
分岐処理が多いですが、以下のようにまとめられます
- ログイン中のユーザーがアカウント移行・統合の条件を満たすとしたら、管理画面上に該当のモーダルやお知らせが表示される
- ユーザーがそのモーダルやお知らせにあるリンクをクリックすると、アカウント移行・統合を確認できる。もちろん情報が欠けたら確認前に入力する必要がある
- ユーザーが確認した後、アカウント移行・統合が実行され、終了する
個人ユーザーの管理画面上でアカウント統合を行う
個人ユーザーとフォロワー両方登録している方も個人ユーザーにログインしてからアカウント統合を実行できます。
個人ユーザーのメールアドレスに該当するフォロワーが存在するかという条件を判定するだけなので、処理がとても簡単です。
最後に
今回のプロジェクトの実装で、フォロワーユーザーと個人ユーザーが自身の操作でアカウントをマイグレーションすることができました。
テーブルの調整やアカウント移行・統合の分岐処理のおかげで、告知期間を経てから、自動的にフォロワーアカウントを個人ユーザーにマイグレーションすることが安易に実装できると思います。