データベースにコメントといいね!を実装する


146

私はソフトウェア開発者です。私はコードを愛して、私は現在、私のように、ユーザがエンティティをマークするために許可されるには、ウェブサイト作成しています...データベースを嫌い言っています(FBでのように)、タグ、それをしてコメントを

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

ここで似たような質問をいくつか見つけましたが、どれも満足のいく答えはありません。そのため、もう一度この質問をします。

質問は適切、方法、である効率的かつ弾力それが異なるため、コメント保存することができるように、データベースを設計テーブルを好き異なるため、テーブルタグ彼らのために。回答としてのいくつかのデザインパターンが最良です;)

詳細な説明:私はテーブル User一部のユーザーデータ、および3つの以上とテーブルをPhoto撮影Articlesとの記事Places場所。ログインしたユーザーが次のことをできるようにしたい:

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

  • それらのいずれかを好きとしてマーク

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

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

1 回目のアプローチ

a)のためのタグ、私が作成するテーブルを Tag [TagId, tagName, tagCounter]、そして私が作成する多対多の関係のテーブルをするために:Photo_has_tagsPlace_has_tagArticle_has_tag

b)コメントも同じです。

C)私が作成するテーブルを LikedPhotos [idUser, idPhoto]LikedArticles[idUser, idArticle]LikedPlace [idUser, idPlace]。多くの同類をして算出されたクエリ(私が悪いと仮定し、)。そして...

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


2 番目のアプローチ

私は、テーブルが作成されますElementType [idType, TypeName == some table name]の名前を持つ管理者(私)によって移入されたテーブルすることができます言っていますコメントタグ付けを。次に、テーブルを作成します。

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. count()を選択します。

私の問題の説明が今より完全であることを望みます。


XMLを検討しましたか?
CodyBugstein 14

1
私の頭の中にあるような100%の質問はめったに見つかりません。あなたの質問は驚くほど完全です。@Kokosに感謝します。
aderchox

回答:


195

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

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

カテゴリー

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

ER図


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

  • 1つのテーブル内のすべてのタイプ。
  • 別の表のすべての具象タイプ。
  • すべての具象型と抽象型は別々のテーブルにあります。

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


2
すばらしい回答、ありがとうございます。私はそれをなんとか実装することを願っています...そして、Django ORMがそれをマップするためにどのように処理するのか(または私が自分でそれをどのように行うのか...しかし、それは別の問題です;))しかし、あなたは説明できますか?私、それが正しく理解していないと思うので-あなたが私のために描いたもの(ありがとう!)は、あなたが言及した3番目のアプローチですか?
Kokos

2
@Kokos基本的に、アプローチ(3)は、ENTITYがテーブル、PHOTOがテーブル、ARTICLEがテーブル、PLACEがテーブルであることを意味します。アプローチ(2)はENTITY テーブルがないことを意味し、アプローチ(1)はテーブルが1つしかないことを意味します。これらすべてのアプローチ(すべて長所と短所を備えている)の存在は、典型的なRDBMSがテーブルの継承をネイティブでサポートしていないという事実の不幸な結果です。
ブランコディミトリエビッチ

1
「カテゴリ」についてのすばらしい説明と参照をありがとう。私はこれに近い質問を投稿するつもりでしたが、あなたはここで答えました。
アンディホラデー

2
@BrankoDimitrijevicエンティティテーブルPhoto、Article、Placeに、PhotoID、ArticleIDなどの独自のPKを設定できないのに、FKとしてEntity_IDの別の列も設定できないのはなぜですか。これは不要ですか?
第1巻

3
@Orionの最大値BIGINTは9223372036854775807です。毎秒1行挿入すると仮定すると、約3,000億年以内に使用可能な値が不足します。確かに、それまでに128ビット整数に移植できます!
ブランコディミトリエビッチ2014年

22

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

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

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

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


2
自分で実装する必要があるからです。少なくとも今のところ...そして、おそらくデータベースを少し好きに始める良い機会だと思いました;)ストアドプロシージャに関する提案についてありがとうございます。Django ORMによって自動的にマッピングされている場合、誰かが知っていますか?
Kokos

6
私はあなたの最後の文を愛しています- それはいつも二回目のほうがいいです。
ルイス

2
二度目はいつも良いです。うん
Gammer

20

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

ここに画像の説明を入力してください

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

この疑似コードは、ID 5のすべての
いいね!またはいいね!のユーザーを取得します(count()を使用して、いいねの数だけを取得できます)

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

コメントの「いいね」リンクをクリックするなど、コメントが好きな方もいらっしゃると思います。このクエリは、ID 133とコメント(アクション)の同類を取得します: SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
user964260

1
私のシステムの今後のリリースでは、この解決策を間違いなく思い出します:)
Kokos

私は2つのスタッフテーブルstuff1とstuff2を持っています...私はこの図に従っていますが、これを使用しているときにSQLエラーがあります... stuff1、stuff2は独立した主キーを持つ2つの独立したテーブルで、アクションテーブルには参照している列id_stuffがありますこれらの2つのタベルstuff1、stuff2。たとえば、stuff1が5行、stuff2が10行の場合、id_stuffが5未満のアクションテーブルに行を追加しようとすると、stuff3とstuff1の両方にid_stuff '3'の行が存在するため、クエリを実行する '3'としましょう。 stuff2、ただしid_stuffが5より大きい行を追加しようとすると...(次のコメントに続く)
vikas devde

1
このようにLikeを実装する場合、新しいLikeをユーザーに通知することが難しくなります。別のテーブルが必要になります。
Greg L

4
どのようになるid_stuffの列は、3つのテーブルのそれぞれに固有の値が含まれていますか?
第1巻

0

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

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

データベースダイアグラムを投稿した場合。私は関係を描くことができます。
erencan

0

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

必要なテーブルの数が少ない方を優先しない場合

この場合:

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

あなたの「差別的な」アプローチであるオプション2は、場合によってはより単純なクエリを生成し、他の場合にはそれほど悪くないように思えるので、私はそれを採用します。


0

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


-1

コメントなどのエンティティごとにテーブルを使用することを検討してください。より多くのテーブル-より良いシャーディングとスケーリング。私が知っているすべてのフレームワークで多くの同様のテーブルを制御することは問題ではありません。

ある日、そのような構造からの読み取りを最適化する必要があります。基本テーブルの上に簡単に悪化するテーブルを作成し、書き込みで少し失うことができます。

辞書のある1つの大きなテーブルは、いつか制御できなくなる可能性があります。


テーブルが多いほど、保守性が低下します。個々のテーブルは、ほとんどのd / bsによって分割できます。
wallyk 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.