Veritabanındaki Yorum ve Beğenilerin Uygulanması


146

Ben bir yazılım geliştiricisiyim. Kodlamayı seviyorum, ancak veritabanlarından nefret ediyorum ... Şu anda, bir kullanıcının bir varlığı sevdiği (FB'deki gibi) olarak işaretlemesine , etiketlemesine ve yorumlamasına izin verilecek bir web sitesi oluşturuyorum .

Bu işlevselliği işlemek için veritabanı tabloları tasarımına takıldım. Çözüm önemsizdir, eğer bunu sadece bir tür şey için yapabilirsek (örn. Fotoğraflar). Ancak bunu 5 farklı şey için etkinleştirmem gerekiyor (şimdilik, ancak tüm hizmet büyüdükçe bu sayının büyüyebileceğini de varsayıyorum).

Burada benzer sorular buldum, ancak hiçbirinin tatmin edici bir cevabı yok, bu yüzden bu soruyu tekrar soruyorum.

Soru, farklı tablolar , farklı tablolar için beğeniler ve onlar için etiketler saklayabilmeleri için veritabanının nasıl düzgün, verimli ve elastik olarak tasarlanacağıdır . Cevap olarak bazı tasarım desen en iyi olacak;)

Ayrıntılı açıklama : Bir sahip tablo User bir kullanıcı verileri ile ve 3 daha fazla tablo : Photoile fotoğrafları , Articlesile eşyalar , Placesile yer . Oturum açmış herhangi bir kullanıcının aşağıdakileri yapmasını sağlamak istiyorum:

  • bu 3 tablodan herhangi birine yorum yap

  • herhangi birini beğendi olarak işaretle

  • herhangi birini bir etiketle etiketleyin

  • Ayrıca her öğe için beğeni sayısını ve belirli bir etiketin kaç kez kullanıldığını saymak istiyorum.

1 st yaklaşım :

a) için etiketleri , bir yaratacak tablo Tag [TagId, tagName, tagCounter] , o zaman yaratacak birçok çoğa ilişkileri tabloları için: Photo_has_tags, Place_has_tag,Article_has_tag .

b) Aynı yorumlar yorumlar için de geçerlidir.

c) Bir yaratacak tablo LikedPhotos [idUser, idPhoto] , LikedArticles[idUser, idArticle], LikedPlace [idUser, idPlace]. Sayısı sever tarafından hesaplanacaktır sorgular (Kötü olduğunu varsayalım). Ve...

Son bölüm için bu tasarımı gerçekten sevmiyorum, benim için kötü kokuyor;)


2 nd yaklaşım :

Ben bir tablo yaratacak ElementType [idType, TypeName == some table name]isimleriyle yönetici (benim) tarafından doldurulur tablolar olabilir sevdim , yorumladı veya etiketlenebilecek . Sonra tablolar oluşturacağım :

a) LikedElement [idLike, idUser, idElementType, idLikedElement] ve her biri için uygun sütunlara sahip Yorumlar ve Etiketler için aynıdır. Şimdi, beğendiğim bir fotoğraf yapmak istediğimde ekleyeceğim:

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

ve yerler için:

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

ve böylece ... İkinci yaklaşımın daha iyi olduğunu düşünüyorum, ama aynı zamanda bu tasarımda bir şey eksik gibi hissediyorum ...

Sonunda, öğenin kaç kez sevildiğine dair sayacı depolamak için en iyi yerin hangisi olduğunu merak ediyorum. Sadece iki yol düşünebilirim:

  1. elemanda (Photo/Article/Place ) tablosunda
  2. select count () ile.

Umarım bu konudaki açıklamam şimdi daha kapsamlı.


XML'i düşündünüz mü?
CodyBugstein

1
Bu tür soruları nadiren% 100 aklımda olan soruları buluyorum, sorunuz inanılmaz derecede eksiksiz! Teşekkürler @Kokos.
aderchox

Yanıtlar:


195

En genişletilebilir çözüm, yalnızca bir "temel" tabloya ("beğeniler", etiketler ve yorumlara bağlı) sahip olmak ve diğer tüm tabloları "devralmak" tır. Yeni bir varlık türü eklemek, sadece yeni bir "miras alınan" tablo eklemeyi içerir - daha sonra otomatik olarak / tag / comment makinelerine otomatik olarak takılır.

Bunun için varlık ilişkisi terimi "kategori" dir ( ERwin Yöntem Kılavuzu , bölüm: "Alt Tür İlişkileri" bölümüne bakın). Kategori sembolü:

Kategori

Bir kullanıcının birden fazla varlığı sevebileceğini varsayarsak, aynı etiket birden fazla varlık için kullanılabilir, ancak yorum varlığa özgüdür, modeliniz şöyle görünebilir:

ER Şeması


BTW, "ER kategorisi" uygulamak için kabaca 3 yol vardır:

  • Tüm tipler tek bir tabloda.
  • Tüm beton tipleri ayrı tablolarda.
  • Ayrı tablolarda tüm somut ve soyut türler.

Çok sıkı performans gereksinimleriniz yoksa, üçüncü yaklaşım muhtemelen en iyisidir (yani, fiziksel tablolar yukarıdaki diyagramdaki varlıklarla 1: 1 ile eşleşir).


2
harika cevap, teşekkür ederim. Umarım uygulamayı başarabilirim ... ve merak ediyorum Django ORM onu haritaya nasıl koyacağını (ya da bunu kendi başıma nasıl yapacağımı ... ama bu başka bir sorun;)) Ama açıklayabilir misin? ben, çünkü ben doğru anlamıyorum sanırım - benim için çizdiğiniz şey (teşekkürler!) bahsettiğiniz üçüncü yaklaşım nedir?
Kokos

2
@Kokos Esasen yaklaşım (3), ENTITY'nin bir tablo, FOTOĞRAF'ın bir tablo, MAKALE bir tablo ve PLACE'in bir tablo olduğu anlamına gelir. Yaklaşım (2) vardır anlamına gelir herhangi tek bir tablo olduğu anlamına üzere taraf ve yaklaşım (1) için tablo. Tüm bu yaklaşımların varlığı (hepsinin güçlü ve zayıf yanlarıyla), tipik bir RDBMS'nin tablo mirasını doğal olarak desteklememesinin talihsiz sonucudur.
Branko Dimitrijevic

1
+1 "kategoriler" ile ilgili harika açıklamalar ve referanslar için teşekkürler. Buna yakın bir soru gönderecektim ama sen burada cevapladın.
andy holaday

2
@BrankoDimitrijevic Varlık neden Fotoğraf, Makale, Yerin tablolarını kendi PK'si yok, örneğin PhotoID, ArticleID vb. Bu gereksiz mi?
cilt bir

3
@Orion için maksimum 9223372036854775807'dir. BIGINTSaniyede bir satır eklediğinizi varsayarsak, ~ 300 milyar yıl içinde mevcut değerleriniz tükenir. Şüphesiz, o zamana kadar 128 bit tamsayılara bağlanabileceksiniz!
Branko Dimitrijevic

22

Veritabanlarından "nefret" ettiğiniz için neden bir tane uygulamaya çalışıyorsunuz? Bunun yerine, bu şeyleri seven ve nefes alan birinden yardım isteyin.

Aksi takdirde, veritabanınızı sevmeyi öğrenin. İyi tasarlanmış bir veritabanı, programlamayı kolaylaştırır, siteyi tasarlar ve sürekli çalışmasını kolaylaştırır. Deneyimli bir d / b tasarımcısı bile tam ve mükemmel bir öngörüye sahip olmayacaktır: kullanım düzenleri ortaya çıktıkça veya gereksinimler değiştikçe yolda bazı şema değişikliklerine ihtiyaç duyulacaktır.

Bu tek kişilik bir projeyse, veritabanı arabirimini saklı yordamları kullanarak basit işlemlere programlayın: add_user, update_user, add_comment, add_like, upload_photo, list_comments, vb. Şemayı tek bir kod satırına gömmeyin. Bu şekilde, veritabanı şeması herhangi bir kodu etkilemeden değiştirilebilir: yalnızca saklı yordamlar şema hakkında bilgi sahibi olmalıdır.

Şemayı birkaç kez yeniden düzenlemeniz gerekebilir. Bu normal. İlk seferde mükemmel hale getirme konusunda endişelenmeyin. Sadece ilk tasarımı prototiplendirecek kadar işlevsel hale getirin. Zamanın lüksüne sahipseniz, biraz kullanın ve şemayı silin ve tekrar yapın. Öyle her zaman iyi ikinci kez.


2
Çünkü bunu kendim uygulamak zorundayım. En azından şimdilik ... ve, belki de bir veritabanını biraz sevmeye başlamanın iyi bir fırsat olduğunu düşündüm;) Saklı yordam ile öneriniz için teşekkür ederiz. Birisi otomatik olarak Django ORM tarafından eşleştirilip eşleştirilmediğini biliyor mu?
Kokos

6
Son cümlenizi seviyorum - İkinci kez her zaman daha iyidir.
Lewis

2
İkinci kez her zaman daha iyidir. Yup
Gammer

20

Bu genel bir fikir, lütfen alan adları stiline çok dikkat etmeyin, ancak ilişki ve yapıya daha fazla dikkat edin.

resim açıklamasını buraya girin

Bu sözde kod, 5 numaralı KİMLİ
SELECT * FROM eylemlerinden fotoğrafın tüm yorumlarını alacak.
Actions.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"

Bu sözde kod, ID 5 ile fotoğrafı seven tüm beğeni veya kullanıcıları
alacaktır (beğenme miktarını almak için count () kullanabilirsiniz)

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

Bir yorumda "beğen" bağlantısını tıklamak gibi yorumları bile beğenebileceğinizi düşünüyorum. Bu sorgu kimliği 133 ile bir yorum (eylem) gibi SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
alacak

1
Sistemimin diğer sürümleri için bu çözümü kesinlikle hatırlayacağım :)
Kokos

2 şey tablo stuff1 ve stuff2 var ... Bu diyagramı takip ettim ama bunu kullanırken sql hatası var ... stuff1, stuff2 bağımsız birincil anahtarları ile iki bağımsız tablolar ve eylem tablosu başvurulan bir sütun id_stuff vardır bu iki tablo şeyler1, şeyler2. Şimdi örneğin stuff1'de 5 satır var, stuff2'de 10 satır var, id_stuff ile eylem tablosuna satır eklemeye çalıştığımda 5'ten az bir şey '3' diyelim sorgu çalıştırıyor çünkü her iki stuff1'de id_stuff '3' ile bir satır var ve stuff2, ancak id_stuff 5'ten büyük bir satır eklemeye çalışırsam ... (bir sonraki yoruma devam et)
Vikas Devde

1
Biri beğenileri bu şekilde uygulamaksa, kullanıcıyı yeni beğenilerin bildirilmesini zorlaştırır. Başka bir tablo gerektiriyordu.
Greg L

4
id_stuffSütun üç tablonun her birinde nasıl benzersiz değerler içerecek?
cilt 1

0

anladığım kadarıyla. birkaç tablo gereklidir. Aralarında çoktan çoka bir ilişki vardır.

  • Ad, soyadı, doğum tarihi gibi kullanıcı verilerini kimlik alanı ile birlikte saklayan tablo.
  • Veri türlerini depolayan tablo. bu tür fotoğraflar fotoğraf, paylaşım, bağlantı olabilir. her türün benzersiz bir tablosu olmalıdır. bu nedenle, kendi tabloları ile bu tablo arasında bir ilişki vardır.
  • her farklı veri türünün tablosu vardır. örneğin, durum güncellemeleri, fotoğraflar, bağlantılar.
  • son tablo, bir kimliği, kullanıcı kimliğini, veri türünü ve veri kimliğini saklamak için birçok ilâve ilişkidir.

veritabanı şemanızı gönderirseniz. İlişkiyi çizebilirim.
erencan

0

İhtiyacınız olacak erişim modellerine bakın. Bunlardan herhangi biri tasarım seçimimi veya diğerini zorlaştırıyor mu?

Eğer az tablo gerektiren bir iyilik değilse

Bu durumda:

  1. Yorum Ekle: Ya belirli bir çok / çok tablo seçin veya sevilen şey için bilinen belirli bir tanımlayıcı ile ortak bir tabloya ekleyin, sanırım istemci kodu ikinci durumda biraz daha basit olacaktır.
  2. Öğe için yorumları bulun: burada ortak bir tablo kullanmak biraz daha kolay görünüyor - sadece varlık türüne göre parametrelenen tek bir sorgu var
  3. Bir kişinin bir tür şeyle ilgili yorumlarını bulma: her iki durumda da basit sorgu
  4. Bir kişi tarafından her şey hakkında tüm yorumları bulun: bu her iki şekilde de biraz çirkin görünüyor.

Bence "ayrımcı" yaklaşım, seçenek 2, bazı durumlarda daha basit sorgular verir ve diğerlerinde çok daha kötü görünmüyor, bu yüzden ben onunla gitmek istiyorum.


0

Kesinlikle bir tablonuz olan ikinci yaklaşıma gidin ve her satır için öğe türünü saklayın, size çok daha fazla esneklik verecektir. Temelde bir şey daha az tablo ile mantıksal olarak yapılabildiğinde, daha az tablo ile gitmek neredeyse her zaman daha iyidir. Şu anda özel durumunuz hakkında aklıma gelen bir avantaj, belirli bir kullanıcının tüm sevilen öğelerini silmek istediğinizi düşünün, ilk yaklaşımınızla her eleman türü için bir sorgu vermeniz gerekir, ancak ikinci yaklaşımla yapılabilir sadece bir sorgu ile veya yeni bir eleman türü eklemek istediğinizde düşünün, ilk yaklaşımla her yeni tür için yeni bir tablo oluşturmayı içerir, ancak ikinci yaklaşımla hiçbir şey yapmamalısınız ...


-1

Yorumlar ve vb. İçin varlık başına tablo kullanmayı düşünün. Daha fazla tablo - daha iyi parçalama ve ölçeklendirme. Bildiğim tüm çerçeveler için birçok benzer tabloyu kontrol etmek sorun değil.

Bir gün bu yapıdaki okumaları optimize etmeniz gerekir. Temel tablolar üzerinde kolayca ağırlaştırıcı tablolar oluşturabilir ve yazma işlemlerinde biraz kaybedebilirsiniz.

Sözlük içeren büyük bir tablo bir gün kontrol edilemez hale gelebilir.


Daha fazla tablo, daha az bakım yapılabileceği anlamına gelir. Bireysel tablolar çoğu d / b tarafından parçalanabilir.
wallyk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.