web-dev-qa-db-ja.com

データベースへのコメントといいねの実装

私はソフトウェア開発者です。私はコーディングが好きですが、データベースは嫌いです...現在、ユーザーがエンティティをliked(FBのように)としてマークできるWebサイトを作成しています、tagitおよびcomment

この機能を処理するためのデータベーステーブルの設計にこだわっています。 1種類の物(写真など)に対してのみこれを行うことができる場合、解決策は簡単です。ただし、これを5つの異なるものに対して有効にする必要があります(現時点では、サービス全体が拡大するにつれて、この数も増えると想定しています)。

ここで似たような質問をいくつか見つけましたが、満足のいく答えがないので、もう一度この質問をしています。

問題は、適切に効率的におよび弾性的にデータベースを設計し、異なるtableslikes異なるtablesおよびtags 彼らのために。答えとしてのいくつかのデザインパターンが最適です;)

詳細な説明tableUserといくつかのユーザーデータ、さらに3つのtablesPhoto withphotographsArticles witharticlesPlaces with場所。ログに記録されたユーザーに次のことを許可したい:

  • これら3つのテーブルのいずれかにコメントする

  • 気に入ったものとしてマークする

  • それらのいずれかに何らかのタグを付けます

  • また、すべての要素のいいねの数と、特定のタグが使用された回数もカウントします。

1st アプローチ

a)tagsの場合、tableTag [TagId, tagName, tagCounter]を作成してから、多対多関係tablesPhoto_has_tagsPlace_has_tagArticle_has_tag

b)コメントについても同様です。

c)tableLikedPhotos [idUser, idPhoto]LikedArticles[idUser, idArticle]LikedPlace [idUser, idPlace]を作成します。 likesの数はqueries(これは悪いと思います)によって計算されます。そして...

私は最後の部分でこのデザインが本当に好きではありません、それは私にとってひどく臭いです;)


2nd アプローチ

管理者(私)にtablesの名前を入力するテーブルElementType [idType, TypeName == some table name]を作成しますlikedコメント付きまたはタグ付き。次に、テーブルを作成します

a)LikedElement [idLike, idUser, idElementType, idLikedElement]およびコメントとタグについても同じで、それぞれに適切な列があります。今、私が好きな写真を作りたいとき、私は挿入します:

typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)

そして場所のために:

typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)

など... 2番目のアプローチの方が良いと思いますが、このデザインにも何かが欠けているように感じます...

最後に、その要素が何回好かれたのか、カウンターを保管するのに最適な場所はどれかと思います。次の2つの方法しか考えられません。

  1. 要素(Photo/Article/Place)テーブル内
  2. select count()によって。

私はこの問題についての私の説明が今より完全であることを望んでいます。

121
Kokos

最も拡張可能なソリューションは、1つの「ベース」テーブル(「いいね」、タグ、コメントに接続)のみを持ち、それから他のすべてのテーブルを「継承」することです。新しい種類のエンティティを追加するには、新しい「継承された」テーブルを追加するだけで済みます。これにより、like/tag/comment機構全体に自動的にプラグインされます。

このためのエンティティ関係の用語は「カテゴリ」です( ERwinメソッドガイド 、セクション:「サブタイプの関係」を参照)。カテゴリシンボルは次のとおりです。

Category

ユーザーが複数のエンティティを好む場合、同じタグを複数のエンティティに使用できますが、コメントはエンティティ固有であるため、モデルは次のようになります。

ER Diagram


ところで、「ERカテゴリ」を実装するには、おおよそ3つの方法があります。

  • 1つのテーブル内のすべてのタイプ。
  • 個別のテーブル内のすべての具象型。
  • 個別のテーブル内のすべての具象型と抽象型。

非常に厳しいパフォーマンス要件がない限り、おそらく3番目のアプローチが最適です(つまり、物理テーブルは上の図のエンティティと1:1で一致します)。

169

データベースが「嫌い」なのに、なぜそれを実装しようとしているのですか?代わりに、このようなものを愛し、呼吸する人に助けを求めてください。

そうでなければ、データベースを愛することを学ぶ。適切に設計されたデータベースは、プログラミングを簡素化し、サイトのエンジニアリングを行い、継続的な運用を円滑にします。経験豊富なd/b設計者でさえ、完全で完全な先見の明はありません。使用パターンの出現や要件の変更に伴い、今後のスキーマの変更が必要になります。

これが1人のプロジェクトである場合は、add_user、update_user、add_comment、add_like、upload_photo、list_commentsなどのストアドプロシージャを使用して、データベースインターフェイスを単純な操作にプログラムします。1行のコードにもスキーマを埋め込まないでください。この方法で、コードに影響を与えずにデータベーススキーマを変更できます。スキーマについては、ストアドプロシージャのみが知っている必要があります。

スキーマを数回リファクタリングする必要がある場合があります。これは正常です。初めて完璧になることを心配しないでください。初期設計のプロトタイプを作成するのに十分なだけ機能的にします。時間に余裕がある場合は、ある程度使用してから、スキーマを削除してからもう一度実行してください。 2回目はalwaysより良いです。

21
wallyk

これは一般的な考え方です。フィールド名のスタイル設定にはあまり注意を払わずに、関係と構造に注意してください。

enter image description here

この擬似コードは、ID 5の写真のすべてのコメントを取得します
SELECT * FROMアクション
Whereアクション.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"

この擬似コードは、ID 5の写真が好きなすべてのいいね!またはユーザーを取得します
(count()を使用して、いいね!の数を取得できます)

SELECT * FROM actions  
WHERE actions.id_Stuff = 5  
AND actions.typeStuff="photo"  
AND actions.typeAction = "like"  
18
user964260

私が理解する限りでは。いくつかのテーブルが必要です。それらの間には多対多の関係があります。

  • 名前、姓、生年月日などのユーザーデータをIDフィールドとともに格納するテーブル。
  • データ型を格納するテーブル。これらのタイプには、写真、共有、リンクがあります。各タイプには一意のテーブルが必要です。したがって、個々のテーブルとこのテーブルの間には関係があります。
  • 異なるデータ型にはそれぞれテーブルがあります。たとえば、ステータスの更新、写真、リンク。
  • 最後のテーブルは、ID、ユーザーID、データ型、データIDを格納する多対多リレーション用です。
0
erencan

必要になるアクセスパターンを見てください。それらのいずれかが、設計の選択のどちらか一方を特に困難または非効率にしているように見えますか?

より少ないテーブルを必要とするものを好まない場合

この場合:

  1. コメントの追加:特定の多/多テーブルを選択するか、好まれているものの既知の特定の識別子を使用して共通テーブルに挿入します。2番目のケースでは、クライアントコードが若干単純になると思います。
  2. アイテムのコメントを検索する:ここでは、共通テーブルを使用する方が少し簡単だと思われます-エンティティのタイプによってパラメータ化された単一のクエリがあります
  3. ある種の事柄についての人からのコメントを検索する:どちらの場合でも簡単なクエリ
  4. すべてのものに関する人によるすべてのコメントを検索します。これはどちらにしても、どちらかと言えば少し気味が悪いようです。

あなたの「差別的な」アプローチ、オプション2は、いくつかのケースではより単純なクエリを生成し、他のケースではそれほど悪くはないと思うので、私はそれで行くと思います。

0
djna

1つのテーブルがあり、各行の要素タイプを格納する2番目のアプローチを使用することは間違いありません。これにより、柔軟性が大幅に向上します。基本的に、より少ないテーブルで何かを論理的に行うことができる場合、ほとんどの場合、より少ないテーブルで行く方が良いです。あなたの特定のケースについて今思い浮かぶ1つの利点は、特定のユーザーの好きな要素をすべて削除することを検討してください。最初のアプローチでは要素タイプごとに1つのクエリを発行する必要がありますが、2番目のアプローチではそれを行うことができますクエリを1つだけ使用するか、新しい要素タイプを追加するタイミングを検討します。最初のアプローチでは新しいタイプごとに新しいテーブルを作成しますが、2番目のアプローチでは何もしないでください...

0
nobody