Skema basis data untuk entitas dengan dua tipe pemilik / induk yang memungkinkan?

8

Saya menggunakan PostgreSQL dengan Sequelize sebagai ORM saya.

Saya punya satu tipe User,. Tipe kedua adalah Group, yang dapat memiliki sejumlah pengguna yang terkait dengannya melalui GroupMembershipstabel. Users juga dapat memiliki sejumlah Groups.

Tipe ketiga saya Playlist,, dapat menjadi milik UserATAU a group. Apa yang akan menjadi cara terbaik untuk merancang skema untuk tipe ini sehingga dapat memiliki satu tipe pemilik atau yang lain?

Pass pertama saya, saya membuat kedua asosiasi, tetapi hanya mengisi satu per satu. Ini mungkin bisa berfungsi, tetapi tampaknya peretasan dan membuat kueri sulit.

Informasi tambahan

Berikut adalah tanggapan saya terhadap permintaan klarifikasi yang diposting oleh MDCCL melalui komentar:

(1) Jika Playlist dimiliki oleh diberikan Grup , dapat dikatakan bahwa ini Playlist berhubungan dengan satu-ke-banyak Pengguna , selama mereka adalah anggota dari seperti Grup , kan?

Saya percaya ini benar secara teknis, tetapi asosiasi satu-ke-banyak ini tidak ada secara eksplisit.

(2) Jadi, mungkinkah Daftar Putar tertentu dimiliki oleh Grup satu-ke-banyak secara bersamaan?

Tidak, seharusnya tidak mungkin Playlistdimiliki oleh satu-ke-banyak Groups.

(3) Apakah mungkin untuk tertentu Playlist untuk dimiliki oleh satu-ke-banyak Grup dan, pada saat yang sama, dengan satu-ke-banyak Pengguna yang tidak Anggota dari seperti Grup ?

Tidak, karena seperti pada (2) satu-ke-banyak dari Playlistke Groupseharusnya tidak ada. Selain itu, jika a Playlistdimiliki oleh a Grouptidak dimiliki oleh a User, dan sebaliknya. Hanya satu pemilik sekaligus.

(4) Apa sajakah properti yang digunakan untuk secara unik mengidentifikasi Grup , Pengguna, dan Daftar Putar ?

Mereka masing-masing memiliki kunci primer pengganti ( id), serta kunci alami (meskipun bukan primer). Ini sluguntuk Groupdan Playlist, dan usernameuntuk User.

(5) Bisakah Playlist tertentu mengalami perubahan Pemilik ?

Walaupun saya tidak berencana ini menjadi fitur (setidaknya pada awalnya), saya kira ini dapat terjadi secara hipotesis.

(6) Apa arti dari atribut Group.Slug dan Playlist.Slug ? Apakah nilainya cukup stabil untuk didefinisikan sebagai kunci utama atau apakah mereka sering berubah? Nilai dari kedua properti ini, bersama dengan Pengguna. Nama pengguna harus unik, benar?

Ini slugadalah versi unik, huruf kecil, ditulis dgn tanda penghubung dari masing-masing entitas mereka title. Misalnya, a groupdengan title'Kelompok Uji' akan memiliki slug'kelompok uji'. Duplikat ditambahkan dengan bilangan bulat tambahan. Ini akan berubah kapan saja titleperubahan mereka . Saya percaya itu berarti mereka tidak akan membuat kunci utama yang hebat? Ya, slugsdan usernamesunik di tabel masing-masing.

Jakemmarsh
sumber

Jawaban:

9

Jika saya memahami spesifikasi Anda dengan baik, skenario Anda melibatkan — di antara aspek-aspek penting lainnya — struktur subtipe-supertipe .

Saya akan mencontohkan di bawah ini bagaimana (1) memodelkannya pada tingkat abstraksi konseptual dan kemudian (2) mewakilinya dalam desain DDL tingkat logis .

Peraturan bisnis

Formulasi konseptual berikut adalah salah satu aturan paling penting dalam konteks bisnis Anda:

  • Sebuah Playlist dimiliki oleh salah tepat satu grup atau tepat satu Pengguna pada titik tertentu dalam waktu
  • Sebuah Playlist dapat dimiliki oleh satu-ke-banyak Grup atau Pengguna pada titik-titik yang berbeda dalam waktu
  • Sebuah Pengguna memiliki nol-satu-atau-banyak Playlist
  • Grup A memiliki nol-satu-atau-banyak Daftar Putar
  • Sebuah kelompok terdiri dari satu-ke-banyak Anggota (yang harus Pengguna )
  • Seorang Pengguna dapat menjadi Anggota dari nol-satu-atau-banyak Grup .
  • Sebuah kelompok terdiri dari satu-ke-banyak Anggota (yang harus Pengguna )

Karena asosiasi atau hubungan (a) antara Pengguna dan Daftar Putar dan (b) antara Grup dan Daftar Putar cukup mirip, fakta ini mengungkapkan bahwa Pengguna dan Grup adalah subtipe entitas yang saling eksklusif dari Pihak 1 , yang pada gilirannya akan menjadi supertipe entitas mereka —supertype- subtipe cluster adalah struktur data klasik yang muncul dalam skema konseptual dari jenis yang sangat beragam—. Dengan cara ini, dua aturan baru dapat ditegaskan:

  • Suatu Pihak dikategorikan oleh tepat satu Jenis Pihak
  • Suatu Pihak adalah Kelompok atau Pengguna

Dan empat aturan sebelumnya harus dirumuskan ulang menjadi hanya tiga:

  • Sebuah Playlist dimiliki oleh tepat satu partai pada titik tertentu dalam waktu
  • Sebuah Playlist dapat dimiliki oleh satu-ke-banyak Pihak pada titik-titik yang berbeda dalam waktu
  • Suatu Pihak memiliki Daftar Putar nol-satu-atau-banyak

Diagram Eksposisi IDEF1X

Diagram IDEF1X 2 yang ditunjukkan pada Gambar 1 mengkonsolidasikan semua aturan bisnis tersebut bersama dengan yang lain yang tampak relevan:

Gambar 1 - Diagram Pemilik IDEF1X Diagram

Seperti yang diperlihatkan, Grup dan Pengguna digambarkan sebagai subtipe yang dihubungkan oleh masing-masing baris dan simbol eksklusif dengan Party , supertype.

The Party.PartyTypeCode properti singkatan dari subtipe diskriminator , yaitu, yang menunjukkan jenis subtipe misalnya harus melengkapi kejadian supertype diberikan.

Juga, Party terhubung dengan Daftar Putar melalui properti OwnerId yang digambarkan sebagai KUNCI LUAR NEGERI yang menunjuk ke Party.PartyId . Dengan cara ini, Pihak saling terkait (a) Daftar Putar dengan (b) Grup dan (c) Pengguna .

Oleh karena itu, karena instance Pihak tertentu adalah Grup atau Pengguna , Daftar Putar tertentu dapat ditautkan dengan paling banyak satu kejadian subtipe.

Tata letak tingkat logis ilustrasi

Diagram IDEF1X yang diuraikan sebelumnya telah melayani saya sebagai platform untuk membuat pengaturan SQL-DDL logis berikut (dan saya telah memberikan catatan sebagai komentar yang menyoroti beberapa poin relevansi tertentu — misalnya, deklarasi kendala—):

-- You should determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- Also, you should make accurate tests to define the 
-- most convenient INDEX strategies based on the exact 
-- data manipulation tendencies of your business domain.

-- As one would expect, you are free to utilize 
-- your preferred (or required) naming conventions. 

CREATE TABLE PartyType ( -- Represents an independent entity type.
    PartyTypeCode CHAR(1)  NOT NULL,
    Name          CHAR(30) NOT NULL,  
    --
    CONSTRAINT PartyType_PK PRIMARY KEY (PartyTypeCode),
    CONSTRAINT PartyType_AK UNIQUE      (Name)  
);

CREATE TABLE Party ( -- Stands for the supertype.
    PartyId         INT       NOT NULL,
    PartyTypeCode   CHAR(1)   NOT NULL, -- Symbolizes the discriminator.
    CreatedDateTime TIMESTAMP NOT NULL,  
    --
    CONSTRAINT Party_PK            PRIMARY KEY (PartyId),
    CONSTRAINT PartyToPartyType_FK FOREIGN KEY (PartyTypeCode)
        REFERENCES PartyType (PartyTypeCode)
);

CREATE TABLE UserProfile ( -- Denotes one of the subtypes. 
    UserId     INT      NOT NULL, -- To be constrained as both (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    UserName   CHAR(30) NOT NULL,  
    FirstName  CHAR(30) NOT NULL,
    LastName   CHAR(30) NOT NULL,
    GenderCode CHAR(3)  NOT NULL,
    BirthDate  DATE     NOT NULL,
    --
    CONSTRAINT UserProfile_PK  PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK1 UNIQUE ( -- Multi-column ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT UserProfile_AK2       UNIQUE (UserName), -- Single-column ALTERNATE KEY.
    CONSTRAINT UserProfileToParty_FK FOREIGN KEY (UserId)
        REFERENCES Party (PartyId)
);

CREATE TABLE MyGroup ( -- Represents the other subtype.
    GroupId INT      NOT NULL, -- To be constrained as both (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Title   CHAR(30) NOT NULL,
    --
    CONSTRAINT Group_PK        PRIMARY KEY (GroupId),
    CONSTRAINT Group_AK        UNIQUE      (Title), -- ALTERNATE KEY.
    CONSTRAINT GroupToParty_FK FOREIGN KEY (GroupId)
        REFERENCES Party (PartyId)
);

CREATE TABLE Playlist ( -- Stands for an independent entity type.
    PlaylistId      INT       NOT NULL,
    OwnerId         INT       NOT NULL,  
    Title           CHAR(30)  NOT NULL,
    CreatedDateTime TIMESTAMP NOT NULL,  
    --
    CONSTRAINT Playlist_PK     PRIMARY KEY (PlaylistId),
    CONSTRAINT Playlist_AK     UNIQUE      (Title),  -- ALTERNATE KEY.
    CONSTRAINT PartyToParty_FK FOREIGN KEY (OwnerId) -- Establishes the relationship with (a) the supertype and (b) through the subtype with (c) the subtypes.
        REFERENCES Party (PartyId)
);

CREATE TABLE GroupMember ( -- Denotes an associative entity type.
    MemberId       INT       NOT NULL, 
    GroupId        INT       NOT NULL,
    IsOwner        BOOLEAN   NOT NULL,    
    JoinedDateTime TIMESTAMP NOT NULL,
    --        
    CONSTRAINT GroupMember_PK              PRIMARY KEY (MemberId, GroupId), -- Composite PRIMARY KEY.
    CONSTRAINT GroupMemberToUserProfile_FK FOREIGN KEY (MemberId)
        REFERENCES UserProfile (UserId),
    CONSTRAINT GroupMemberToMyGroup_FK     FOREIGN KEY (GroupId)
        REFERENCES MyGroup (GroupId)  
);

Tentu saja, Anda dapat membuat satu atau lebih penyesuaian sehingga semua karakteristik konteks bisnis Anda diwakili dengan ketelitian yang dibutuhkan dalam database aktual.

Catatan : Saya telah menguji tata letak logis di atas pada db <> biola ini dan juga pada SQL Fiddle ini , keduanya "berjalan" pada PostgreSQL 9.6, sehingga Anda dapat melihat mereka "sedang beraksi".

Siput

Seperti yang Anda lihat, saya tidak memasukkan Group.Slugatau Playlist.Slugsebagai kolom dalam deklarasi DDL. Ini karena, sesuai dengan penjelasan Anda berikut

Ini slugadalah versi unik, huruf kecil, ditulis dgn tanda penghubung dari masing-masing entitas mereka title. Misalnya, a groupdengan title'Kelompok Uji' akan memiliki slug'kelompok uji'. Duplikat ditambahkan dengan bilangan bulat tambahan. Ini akan berubah kapan saja titleperubahan mereka . Saya percaya itu berarti mereka tidak akan membuat kunci utama yang hebat? Ya, slugsdan usernamesunik di tabel masing-masing.

orang dapat menyimpulkan bahwa nilai-nilai mereka dapat diturunkan (yaitu, mereka harus dihitung atau dihitung dalam hal yang sesuai Group.Titledan Playlist.Titlenilai - nilai, kadang-kadang dalam hubungannya dengan -Saya berasumsi, semacam sistem yang dihasilkan- INTEGER), jadi saya tidak akan menyatakan kolom kata di salah satu tabel dasar karena mereka akan memperkenalkan penyimpangan pembaruan.

Sebaliknya, saya akan menghasilkan Slugs

  • mungkin, dalam tampilan , yang (a) termasuk derivasi dari nilai-nilai tersebut dalam kolom virtual dan (b) dapat digunakan secara langsung dalam operasi SELECT selanjutnya — menambahkan bagian INTEGER dapat diperoleh, misalnya, dengan menggabungkan nilai (1) yang Playlist.OwnerIddengan (2) tanda hubung menengah dan (3) nilai Playlist.Title;

  • atau, berdasarkan kode program aplikasi, meniru pendekatan yang dijelaskan sebelumnya (mungkin secara prosedural), setelah set data terkait diambil dan diformat untuk interpretasi pengguna akhir.

Dengan cara ini, salah satu dari dua metode akan menghindari “update sinkronisasi” mekanisme yang harus diletakkan di tempat IFF yang Slugsdipertahankan dalam kolom tabel dasar.

Pertimbangan integritas dan konsistensi

Sangat penting untuk menyebutkan bahwa (i) setiap Party baris harus dilengkapi setiap saat dengan (ii) masing-masing rekan tepat di salah satu tabel yang berdiri untuk subtipe, yang (iii) harus "mematuhi" nilai yang terkandung dalam Party.PartyTypeCodekolom —Mencatat pembeda—.

Akan sangat menguntungkan untuk menegakkan situasi semacam itu secara deklaratif , tetapi tidak ada sistem manajemen basis data SQL utama (termasuk Postgres) yang memasok instrumen yang diperlukan untuk melanjutkan seperti itu; oleh karena itu, menulis kode prosedural dalam TRANSAKSI ASAM sejauh ini merupakan pilihan terbaik untuk menjamin bahwa keadaan yang dijelaskan sebelumnya selalu dipenuhi dalam database Anda. Kemungkinan lain akan beralih ke PEMICU, tetapi mereka cenderung membuat hal-hal berantakan, sehingga untuk berbicara.

Kasus yang sebanding

Jika Anda ingin membuat beberapa analogi, Anda mungkin tertarik untuk melihat jawaban saya untuk pertanyaan (baru) yang berjudul

karena skenario yang sebanding dibahas.


Catatan akhir

1 Pihak adalah istilah yang digunakan dalam konteks hukum ketika merujuk pada individu atau kelompok individu yang membentuk satu entitas , sehingga denominasi ini cocok untuk mewakili konsep Pengguna dan Grup sehubungan dengan lingkungan bisnis yang dimaksud.

2 Definisi Integrasi untuk Pemodelan Informasi ( IDEF1X ) adalah teknik pemodelan data yang sangat direkomendasikan yang ditetapkan sebagai standar pada bulan Desember 1993 oleh Institut Standar dan Teknologi Nasional (NIST)Amerika Serikat. Ini didasarkan pada (a) beberapa karya teoritis awal yang ditulis oleh satu-satunya pencetus model relasional , yaitu, Dr. EF Codd ; pada (b) pandangan entitas-hubungan , yang dikembangkan oleh Dr. PP Chen ; dan juga pada (c) Teknik Desain Basis Data Logis, yang dibuat oleh Robert G. Brown.

MDCCL
sumber
Saya tidak melihat adanya kendala untuk pesta persis salah satu pengguna atau grup
Jasen
Sepertinya komentar Anda berkaitan dengan kutipan pertanyaan berikut (keduanya terkandung dalam bagian yang berjudul “Pertimbangan integritas dan konsistensi”):
MDCCL
Sangat penting untuk menyebutkan bahwa (i) setiap Partybaris harus dilengkapi setiap saat dengan (ii) mitra masing-masing tepat di salah satu tabel yang berdiri untuk subtipe, yang (iii) harus 'mematuhi' nilai yang terkandung dalam Party.PartyTypeCodekolom —ditandai pembeda— ".
MDCCL
Akan sangat menguntungkan untuk menegakkan situasi semacam itu secara deklaratif , tetapi tidak ada sistem manajemen basis data SQL utama (termasuk Postgres) yang memasok instrumen yang diperlukan untuk melanjutkan seperti itu; oleh karena itu, menulis kode prosedural dalam TRANSAKSI ASAM sejauh ini merupakan pilihan terbaik untuk menjamin bahwa keadaan yang dijelaskan sebelumnya selalu dipenuhi dalam database Anda. Kemungkinan lain akan beralih ke PEMICU, tetapi mereka cenderung membuat hal-hal berantakan, sehingga untuk berbicara ”.
MDCCL
Oleh karena itu, sekali (semoga segera) persediaan Postgres, katakanlah, ASSERTIONS, saya akan dengan senang hati memasukkan batasan (deklaratif) yang berlaku. Untuk saat ini, dua pendekatan yang disediakan-DBMS tersedia disarankan di atas.
MDCCL