Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Balasan Komentar Berjenjang:Tampilan dan Penyimpanan

Ada banyak cara. Inilah salah satu pendekatan yang saya sukai (dan gunakan secara teratur).

Basis data

Perhatikan struktur database berikut:

CREATE TABLE comments (
  id int(11) unsigned NOT NULL auto_increment,
  parent_id int(11) unsigned default NULL,
  parent_path varchar(255) NOT NULL,

  comment_text varchar(255) NOT NULL,
  date_posted datetime NOT NULL,  

  PRIMARY KEY  (id)
);

data Anda akan terlihat seperti ini:

+-----+-------------------------------------+--------------------------+---------------+
| id  | parent_id | parent_path             | comment_text             | date_posted   |
+-----+-------------------------------------+--------------------------+---------------+
|   1 | null      | /                       | I'm first                | 1288464193    | 
|   2 | 1         | /1/                     | 1st Reply to I'm First   | 1288464463    | 
|   3 | null      | /                       | Well I'm next            | 1288464331    | 
|   4 | null      | /                       | Oh yeah, well I'm 3rd    | 1288464361    | 
|   5 | 3         | /3/                     | reply to I'm next        | 1288464566    | 
|   6 | 2         | /1/2/                   | this is a 2nd level reply| 1288464193    | 

... and so on...

Cukup mudah untuk memilih semuanya dengan cara yang bisa digunakan:

select id, parent_path, parent_id, comment_text, date_posted
from comments 
order by parent_path, date_posted;

memesan dengan parent_path, date_posted biasanya akan memberikan hasil sesuai urutan yang Anda perlukan saat membuat halaman; tetapi Anda ingin memastikan bahwa Anda memiliki indeks pada tabel komentar yang akan mendukung hal ini dengan baik -- jika tidak, kueri berfungsi, tetapi benar-benar tidak efisien:

create index comments_hier_idx on comments (parent_path, date_posted);

Untuk setiap komentar tunggal yang diberikan, mudah untuk mendapatkan seluruh pohon komentar anak dari komentar itu. Cukup tambahkan klausa where:

select id, parent_path, parent_id, comment_text, date_posted
from comments 
where parent_path like '/1/%'
order by parent_path, date_posted;

klausa where yang ditambahkan akan menggunakan indeks yang sama yang telah kita definisikan, jadi kita siap melakukannya.

Perhatikan bahwa kami belum menggunakan parent_id belum. Sebenarnya, itu tidak sepenuhnya diperlukan. Tapi saya memasukkannya karena memungkinkan kita untuk mendefinisikan kunci asing tradisional untuk menegakkan integritas referensial dan untuk mengimplementasikan penghapusan dan pembaruan berjenjang jika kita mau. Batasan kunci asing dan aturan cascading hanya tersedia di tabel INNODB:

ALTER TABLE comments ENGINE=InnoDB;

ALTER TABLE comments 
  ADD FOREIGN KEY ( parent_id ) REFERENCES comments 
    ON DELETE CASCADE 
    ON UPDATE CASCADE;

Mengelola Hirarki

Untuk menggunakan pendekatan ini, tentu saja, Anda harus memastikan bahwa Anda menyetel parent_path dengan benar ketika Anda memasukkan setiap komentar. Dan jika Anda memindahkan komentar (yang memang merupakan kasus penggunaan yang aneh), Anda harus memastikan bahwa Anda secara manual memperbarui setiap parent_path dari setiap komentar yang berada di bawah komentar yang dipindahkan. ... tetapi keduanya adalah hal yang cukup mudah untuk diikuti.

Jika Anda benar-benar ingin menjadi mewah (dan jika db Anda mendukungnya), Anda dapat menulis pemicu untuk mengelola parent_path secara transparan -- Saya akan membiarkan ini sebagai latihan untuk pembaca, tetapi ide dasarnya adalah bahwa pemicu penyisipan dan pembaruan akan diaktifkan sebelum insert baru dilakukan. mereka akan berjalan ke atas pohon (menggunakan parent_id hubungan kunci asing), dan membangun kembali nilai parent_path sesuai.

Bahkan dimungkinkan untuk memecahkan parent_path keluar ke tabel terpisah yang dikelola sepenuhnya oleh pemicu di tabel komentar, dengan beberapa tampilan atau prosedur tersimpan untuk menerapkan berbagai kueri yang Anda butuhkan. Jadi benar-benar mengisolasi kode tingkat menengah Anda dari kebutuhan untuk mengetahui atau peduli tentang mekanisme penyimpanan info hierarki.

Tentu saja, tidak ada barang mewah yang diperlukan dengan cara apa pun -- biasanya cukup dengan memasukkan parent_path ke dalam tabel, dan menulis beberapa kode di tingkat menengah Anda untuk memastikan bahwa kode tersebut dikelola dengan baik bersama dengan semua bidang lainnya Anda sudah harus mengelola.

Memberlakukan batasan

MySQL (dan beberapa database lainnya) memungkinkan Anda untuk memilih "halaman" data menggunakan LIMIT klausa:

SELECT * FROM mytable LIMIT 25 OFFSET 0;

Sayangnya, ketika berurusan dengan data hierarkis seperti ini, klausa LIMIT saja tidak akan memberikan hasil yang diinginkan.

-- the following will NOT work as intended

select id, parent_path, parent_id, comment_text, date_posted
from comments 
order by parent_path, date_posted
LIMIT 25 OFFSET 0;

Sebagai gantinya, kita perlu memilih secara terpisah pada tingkat di mana kita ingin menerapkan batas, lalu kita menggabungkannya kembali dengan kueri "sub-pohon" kita untuk memberikan hasil akhir yang diinginkan.

Sesuatu seperti ini:

select 
  a.*
from 
  comments a join 
  (select id, parent_path 
    from comments 
    where parent_id is null
  order by parent_path, post_date DESC 
  limit 25 offset 0) roots
  on a.parent_path like concat(roots.parent_path,roots.id,'/%') or a.id=roots.id)
order by a.parent_path , post_date DESC;

Perhatikan pernyataan limit 25 offset 0 , terkubur di tengah pilih dalam. Pernyataan ini akan mengambil 25 komentar "tingkat akar" terbaru.

[Sunting:Anda mungkin menemukan bahwa Anda harus bermain dengan hal-hal sedikit untuk mendapatkan kemampuan untuk memesan dan/atau membatasi hal-hal persis seperti yang Anda suka. ini mungkin termasuk menambahkan informasi dalam hierarki yang dikodekan dalam parent_path . misalnya:alih-alih /{id}/{id2}/{id3}/ , Anda dapat memutuskan untuk menyertakan post_date sebagai bagian dari parent_path:/{id}:{post_date}/{id2}:{post_date2}/{id3}:{post_date3}/ . Ini akan sangat memudahkan untuk mendapatkan urutan dan hierarki yang Anda inginkan, dengan mengorbankan keharusan mengisi kolom di awal, dan mengelolanya saat data berubah]

semoga membantu. semoga berhasil!



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Java/Mysql..SQLException:Sebuah tabel harus memiliki setidaknya 1 kolom SQLState:42000 VendorError:1113

  2. Urutan Operasi MySQL?

  3. Apa cara terbaik untuk mengenkripsi/mendekripsi string json

  4. cara memangkas angka nol di depan dari teks alfanumerik di fungsi mysql

  5. SQL fixed-value IN() vs. INNER JOIN performance