Menerapkan Komentar dan Suka dalam database

146

Saya seorang pengembang perangkat lunak. Saya suka kode, tapi saya benci database ... Saat ini, saya membuat situs web di mana pengguna akan diizinkan untuk menandai entitas yang disukai (seperti di FB), beri tag dan komentar .

Saya terjebak pada desain tabel database untuk menangani fungsi ini. Solusi itu sepele, jika kita bisa melakukan ini hanya untuk satu jenis hal (mis. Foto). Tetapi saya perlu mengaktifkan ini untuk 5 hal yang berbeda (untuk saat ini, tetapi saya juga berasumsi bahwa jumlah ini dapat bertambah, seiring dengan meningkatnya seluruh layanan).

Saya menemukan beberapa pertanyaan serupa di sini, tetapi tidak ada yang memiliki jawaban yang memuaskan, jadi saya mengajukan pertanyaan ini lagi.

Pertanyaannya adalah, bagaimana mendesain database dengan benar, efisien dan elastis , sehingga dapat menyimpan komentar untuk tabel yang berbeda , suka untuk tabel yang berbeda dan tag untuk mereka. Beberapa pola desain sebagai jawaban akan lebih baik;)

Penjelasan terperinci : Saya memiliki tabel User dengan beberapa data pengguna, dan 3 tabel lagi : Photodengan foto , Articlesdengan artikel , Placesdengan tempat . Saya ingin mengaktifkan semua pengguna yang login untuk:

  • mengomentari salah satu dari 3 tabel tersebut

  • tandai salah satu dari mereka sebagai disukai

  • tandai salah satu dari mereka dengan beberapa tag

  • Saya juga ingin menghitung jumlah suka untuk setiap elemen dan berapa kali tag tertentu digunakan.

1 st pendekatan :

a) Untuk tag , saya akan membuat tabel Tag [TagId, tagName, tagCounter] , maka saya akan membuat banyak-ke-banyak hubungan tabel untuk: Photo_has_tags, Place_has_tag, Article_has_tag.

b) Jumlah yang sama untuk komentar.

c) Aku akan membuat tabel LikedPhotos [idUser, idPhoto] , LikedArticles[idUser, idArticle], LikedPlace [idUser, idPlace]. Jumlah suka akan dihitung oleh kueri (yang, saya anggap buruk). Dan...

Saya benar-benar tidak suka desain ini untuk bagian terakhir, baunya buruk bagi saya;)


2 nd pendekatan :

Saya akan membuat tabel ElementType [idType, TypeName == some table name]yang akan diisi oleh administrator (saya) dengan nama-nama tabel yang dapat disukai , dikomentari atau ditandai . Maka saya akan membuat tabel :

a) LikedElement [idLike, idUser, idElementType, idLikedElement]dan sama untuk Komentar dan Tag dengan kolom yang tepat untuk masing-masing. Sekarang, ketika saya ingin membuat foto disukai saya akan memasukkan:

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

dan untuk tempat:

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

dan seterusnya ... Saya pikir pendekatan kedua lebih baik, tetapi saya juga merasa ada sesuatu yang hilang dalam desain ini juga ...

Akhirnya, saya juga bertanya-tanya di mana tempat terbaik untuk menyimpan counter berapa kali elemen itu disukai. Saya hanya bisa memikirkan dua cara:

  1. dalam Photo/Article/Placetabel elemen ( )
  2. dengan pilih count ().

Saya harap penjelasan saya tentang masalah ini lebih menyeluruh sekarang.

Kokos
sumber
Sudahkah Anda mempertimbangkan XML?
CodyBugstein
1
Saya jarang menemukan pertanyaan seperti ini yang 100% apa yang ada dalam pikiran saya, pertanyaan Anda sangat lengkap! Terima kasih @Kokos.
aderchox

Jawaban:

195

Solusi yang paling dapat dikembangkan adalah memiliki hanya satu "basis" tabel (terhubung ke "suka", tag dan komentar), dan "mewarisi" semua tabel lain darinya. Menambahkan jenis entitas baru melibatkan hanya dengan menambahkan tabel "baru" - itu kemudian secara otomatis dihubungkan ke seluruh mesin suka / tag / komentar.

Istilah entitas-hubungan untuk ini adalah "kategori" (lihat Panduan Metode ERwin , bagian: "Hubungan Subtipe"). Simbol kategori adalah:

Kategori

Dengan asumsi pengguna dapat menyukai banyak entitas, tag yang sama dapat digunakan untuk lebih dari satu entitas tetapi komentar bersifat spesifik entitas, model Anda dapat terlihat seperti ini:

Diagram ER


BTW, ada sekitar 3 cara untuk menerapkan "kategori ER":

  • Semua tipe dalam satu tabel.
  • Semua jenis beton dalam tabel terpisah.
  • Semua tipe konkret dan abstrak dalam tabel terpisah.

Kecuali Anda memiliki persyaratan kinerja yang sangat ketat, pendekatan ketiga mungkin yang terbaik (artinya tabel fisik cocok dengan 1: 1 entitas dalam diagram di atas).

Branko Dimitrijevic
sumber
2
jawaban yang bagus, terima kasih Saya harap, saya akan berhasil mengimplementasikannya ... dan saya ingin tahu bagaimana Django ORM akan menangani untuk memetakannya (atau bagaimana saya akan melakukannya sendiri ... tapi, itu masalah lain;)) Tapi, bisakah Anda menjelaskannya? saya, karena saya pikir saya tidak memahaminya dengan benar - apa yang telah Anda buat untuk saya (terima kasih!) adalah pendekatan ketiga yang Anda sebutkan?
Kokos
2
@Kokos Pada dasarnya, pendekatan (3) berarti ENTITY adalah sebuah tabel, PHOTO adalah sebuah tabel, ARTICLE adalah sebuah tabel dan PLACE adalah sebuah tabel. Pendekatan (2) berarti tidak ada tabel untuk ENTITY dan pendekatan (1) akan berarti hanya ada satu tabel. Keberadaan semua pendekatan ini (semua dengan kekuatan dan kelemahannya) adalah konsekuensi yang tidak menguntungkan dari kenyataan bahwa RDBMS yang khas tidak mendukung warisan tabel secara asli.
Branko Dimitrijevic
1
+1 terima kasih atas penjelasan dan referensi yang bagus tentang "kategori". Saya akan memposting pertanyaan dekat dengan ini tetapi Anda menjawabnya di sini.
andy holaday
2
@BrankoDimitrijevic Mengapa entitas tidak dapat membuat tabel Foto, Artikel, Tempat memiliki PK mereka sendiri misalnya PhotoID, ArticleID dll tetapi juga memiliki kolom lain untuk Entity_ID sebagai FK? Apakah ini tidak perlu?
volume satu
3
@Orion Maksimal untuk BIGINTadalah 9223372036854775807. Dengan asumsi Anda memasukkan satu baris setiap detik, Anda akan kehabisan nilai yang tersedia dalam ~ 300 miliar tahun. Tentunya, Anda akan dapat melakukan porting ke integer 128-bit saat itu!
Branko Dimitrijevic
22

Karena Anda "membenci" database, mengapa Anda mencoba mengimplementasikannya? Sebagai gantinya, mintalah bantuan dari seseorang yang mencintai dan bernafas dalam hal ini.

Kalau tidak, belajarlah untuk mencintai basis data Anda. Basis data yang dirancang dengan baik menyederhanakan pemrograman, merekayasa situs, dan memperlancar operasinya. Bahkan seorang desainer d / b yang berpengalaman tidak akan memiliki pandangan ke depan yang lengkap dan sempurna: beberapa perubahan skema akan dibutuhkan saat pola penggunaan muncul atau persyaratan berubah.

Jika ini adalah proyek satu orang, programkan antarmuka basis data menjadi operasi sederhana menggunakan prosedur tersimpan: add_user, update_user, add_comment, add_like, upload_photo, list_comments, dll. Jangan menanamkan skema ke dalam satu baris kode pun. Dengan cara ini, skema database dapat diubah tanpa memengaruhi kode apa pun: hanya prosedur tersimpan yang harus tahu tentang skema tersebut.

Anda mungkin harus memperbaiki skema beberapa kali. Ini normal. Jangan khawatir tentang menyempurnakannya untuk pertama kali. Jadikan itu cukup fungsional untuk membuat prototipe desain awal. Jika Anda memiliki banyak waktu, gunakan beberapa, lalu hapus skema dan lakukan lagi. Itu selalu lebih baik yang kedua kalinya.

wallyk
sumber
2
Karena saya perlu mengimplementasikannya sendiri. Setidaknya untuk saat ini ... dan, saya pikir mungkin ini adalah kesempatan yang baik untuk mulai sedikit menyukai basis data;) Terima kasih tentang saran Anda dengan prosedur tersimpan. Apakah ada yang tahu, jika mereka dipetakan oleh Django ORM secara otomatis?
Kokos
6
Saya suka kalimat terakhir Anda - Itu selalu lebih baik yang kedua kalinya.
Lewis
2
Itu selalu lebih baik yang kedua kalinya. Yup
Gammer
20

Ini adalah ide umum, tolong jangan terlalu memperhatikan gaya nama bidang, tetapi lebih pada hubungan dan struktur

masukkan deskripsi gambar di sini

Pseudocode ini akan mendapatkan semua komentar foto dengan ID 5
SELECT * DARI tindakan
WHERE action.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"

Kodesemu ini akan mendapatkan semua suka atau pengguna yang menyukai foto dengan ID 5
(Anda dapat menggunakan count () untuk mendapatkan jumlah suka)

SELECT * FROM actions  
WHERE actions.id_Stuff = 5  
AND actions.typeStuff="photo"  
AND actions.typeAction = "like"  
pengguna964260
sumber
Saya pikir Anda bahkan mungkin menyukai komentar, seperti mengklik tautan "suka" di komentar. Permintaan ini akan mendapatkan suka dari komentar (tindakan) dengan ID 133: SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
user964260
1
Saya pasti akan mengingat solusi ini untuk rilis lebih lanjut dari sistem saya :)
Kokos
Saya punya 2 tabel hal stuff1 dan stuff2 ... Saya mengikuti diagram ini tetapi ada kesalahan sql saat menggunakan ini ... stuff1, stuff2 adalah dua tabel independen dengan kunci primer independen mereka, dan tabel tindakan memiliki kolom id_stuff yang merujuk ke dua tabel ini stuff1, stuff2. Sekarang misalnya stuff1 memiliki 5 baris, stuff2 memiliki 10 baris, ketika saya mencoba untuk menambahkan baris dalam tabel tindakan dengan id_stuff apa pun yang kurang dari 5 katakanlah '3' itu mengeksekusi permintaan karena ada baris dengan id_stuff '3' di kedua stuff1 dan stuff2, tetapi jika saya mencoba menambahkan baris dengan id_stuff lebih besar dari 5 ... (lanjut ke komentar berikutnya)
vikas devde
1
Jika seseorang menerapkan suka dengan cara ini, itu membuat memberi tahu pengguna suka baru lebih sulit. Itu akan membutuhkan meja lain.
Greg L
4
Bagaimana id_stuffkolom tersebut berisi nilai unik di masing-masing dari tiga tabel?
volume satu
0

sejauh yang saya mengerti. diperlukan beberapa tabel. Ada banyak hubungan di antara mereka.

  • Tabel yang menyimpan data pengguna seperti nama, nama keluarga, tanggal lahir dengan bidang identitas.
  • Tabel yang menyimpan tipe data. jenis ini dapat berupa foto, bagikan, tautan. setiap jenis harus memiliki tabel unik. oleh karena itu, ada hubungan antara tabel masing-masing dan tabel ini.
  • setiap tipe data yang berbeda memiliki tabelnya. misalnya, pembaruan status, foto, tautan.
  • tabel terakhir adalah untuk banyak relasi yang menyimpan id, id pengguna, tipe data, dan id data.
erencan
sumber
jika Anda memposting diagram basis data Anda. saya bisa menggambar relasinya.
erencan
0

Lihatlah pola akses yang akan Anda butuhkan. Apakah ada di antara mereka yang membuat pilihan desain saya sulit atau tidak efisien?

Jika tidak mendukung yang membutuhkan lebih sedikit tabel

Pada kasus ini:

  1. Tambahkan Komentar: Anda dapat memilih banyak / banyak tabel tertentu atau memasukkan ke dalam tabel umum dengan pengenal spesifik yang diketahui untuk apa yang disukai, saya pikir kode klien akan sedikit lebih sederhana dalam kasus kedua Anda.
  2. Temukan komentar untuk item: di sini tampaknya menggunakan tabel umum sedikit lebih mudah - kami hanya memiliki satu parameter permintaan berdasarkan jenis entitas
  3. Temukan komentar oleh seseorang tentang satu hal: permintaan sederhana dalam kedua kasus tersebut
  4. Temukan semua komentar oleh seseorang tentang semua hal: sepertinya ini sedikit tidak penting.

Saya pikir pendekatan "diskriminatif" Anda, opsi 2, menghasilkan pertanyaan yang lebih sederhana dalam beberapa kasus dan tampaknya tidak jauh lebih buruk dalam kasus lain sehingga saya akan melakukannya.

djna
sumber
0

Jelas pergi dengan pendekatan kedua di mana Anda memiliki satu tabel dan menyimpan tipe elemen untuk setiap baris, itu akan memberi Anda lebih banyak fleksibilitas. Pada dasarnya ketika sesuatu secara logis dapat dilakukan dengan lebih sedikit tabel, hampir selalu lebih baik untuk pergi dengan lebih sedikit tabel. Satu keuntungan yang muncul di benak saya saat ini tentang kasus khusus Anda, pertimbangkan Anda ingin menghapus semua elemen yang disukai pengguna tertentu, dengan pendekatan pertama Anda, Anda perlu mengeluarkan satu permintaan untuk setiap jenis elemen tetapi dengan pendekatan kedua itu dapat dilakukan dengan hanya satu kueri atau pertimbangkan ketika Anda ingin menambahkan tipe elemen baru, dengan pendekatan pertama melibatkan membuat tabel baru untuk setiap tipe baru tetapi dengan pendekatan kedua Anda tidak boleh melakukan apa pun ...

tak seorangpun
sumber
-1

Pertimbangkan untuk menggunakan tabel per entitas untuk komentar dan lain-lain. Lebih banyak tabel - sharding dan scaling yang lebih baik. Ini bukan masalah untuk mengontrol banyak tabel yang serupa untuk semua framework yang saya tahu.

Suatu hari Anda harus mengoptimalkan bacaan dari struktur tersebut. Anda dapat dengan mudah membuat tabel agragasi dari basis dan kehilangan sedikit waktu menulis.

Satu meja besar dengan kamus mungkin menjadi tidak terkendali suatu hari.

Oroboros102
sumber
Lebih banyak tabel berarti itu akan kurang dipelihara. Tabel individual dapat di-shard oleh sebagian besar d / bs.
wallyk