2016-12-05 15 views
13

Jestem na rozdrożu decydując, czy tagi powinny być ich własnym zasobem, czy zagnieżdżoną własnością notatki. To pytanie dotyczy nieco RESTful projektowania i przechowywania bazy danych.Czy tag powinien być jego własnym zasobem lub zagnieżdżoną własnością?

Kontekst: Mam zasób notatki. Użytkownicy mogą mieć wiele notatek. Każda notatka może mieć wiele znaczników.

Cele funkcjonalne: muszę tworzyć trasy, wykonaj następujące czynności:
1) Pobiera wszystkie tagi użytkowników. Coś jak: GET /users/:id/tags
2) Usuń znaczniki powiązane z notatką.
3) Dodaj znacznik do określonej notatki.

danych/Występ Gole
1) pobierania tagów użytkownik powinien być szybki. Ma to na celu "autosugest"/"autouzupełnianie".
2) Zapobiegaj duplikatom (w miarę możliwości). Chcę, aby znaczniki były ponownie wykorzystywane w największym możliwym stopniu w celu umożliwienia przesyłu danych według tagów. Na przykład chciałbym złagodzić scenariusze, w których użytkownik wpisuje tag, na przykład "superbohaterowie", gdy tag "superbohater" już istnieje.

takiej sytuacji, tak jak ja to widzę, istnieją dwa sposoby przechowywania tagi na zasób UWAGA:

1) Tagi jako zagnieżdżony nieruchomości. Na przykład:

type: 'notes', 
attributes: { 
    id: '123456789', 
    body: '...', 
    tags: ['batman', 'superhero'] 
} 

2) tagi jako własny zasób. Na przykład:

type: 'notes', 
data: { 
    id: '123456789', 
    body: '...', 
    tags: [1,2,3] // <= Tag IDs instead of strings 
} 

jednej ze podejść powyżej może działać, ale szukam rozwiązania, które pozwoli skalowalność i spójność danych (wyobrazić milion notatek i dziesięć milionów tagów). W tym momencie pochylam się do opcji nr 1, ponieważ łatwiej jest poradzić sobie z kodowaniem, ale niekoniecznie jest to właściwa opcja.

Jestem bardzo zainteresowany słuchaniem myśli na temat różnych podejść, szczególnie, że nie mogę znaleźć podobnych pytań na SO dotyczących tego tematu.

Aktualizacja Dziękuję za odpowiedzi. Jedną z najważniejszych rzeczy dla mnie jest określenie, dlaczego korzystanie z jednego na drugim jest korzystne. Chciałbym, żeby odpowiedź zawierała trochę listy pro/con.

+0

Mówisz o tym podczas przechowywania w DB lub kiedy dane wyjściowe są zwracane z reszty? –

+0

Czy w tagu są jakieś inne informacje oprócz imienia i nazwiska, a może również ID? –

+0

Tagi zawierają tylko wartość ciągu. To pytanie dotyczy zarówno projektu RESTful, jak i pamięci DB - zaktualizowałem moje pytanie, aby to odzwierciedlić. –

Odpowiedz

6

tl; dr

Biorąc pod uwagę wymagania, IMO należy przechowywać tags jako zasobów a API powinien zwrócić notes z tagami jak wbudowanych właściwości.


projekt Database

Przechowywać notes i tags jako oddzielnych zbiorów (lub tabel). Ponieważ masz wiele notatek i znaczników oraz biorąc pod uwagę fakt, że podstawowa funkcjonalność zależy od wyszukiwania/autouzupełniania na tych tags, poprawi to wydajność podczas wyszukiwania notes dla konkretnego tags. To bardzo prosty projekt może wyglądać następująco:

notatki

{ 
    'id': 101, // noteid 
    'title': 'Note title', 
    'body': 'Some note', 
    'tags': ['tag1', 'tag2', ...] 
} 

tagi

{ 
    'id': 'tag1', // tagid 
    'name': 'batman', 
    'description': 'the dark knight', 
    'related': ['tagx', 'tagy', ...], 
    'notes': [101, 103, ...] 
} 

Można użyć właściwości related obsługiwać duplikaty zastępując tagx, tagy o podobnym tags.


API Projekt

1. Pobieranie notes dla user:

GET /users/{userid}/notes 

osadzić tags w obiekcie notes gdy obsługiwać tę trasę w backend. notes przedmiot Twój API wyślij powinien wyglądać mniej więcej tak:

{ 
    'id': 101, 
    'title': 'Note title', 
    'body': 'Some note', 
    'tags': ['batman'] // replacing the tag1 by its name from tag collection 
} 

2. Pobieranie tags dla user:

GET /users/{userid}/tags 

Jeśli nie jest to konieczne, można pominąć na wysyłanie właściwość notes który zawiera id dla twojego notes.

3.Usuwanie tags dla notes:

DELETE /users/{userid}/{noteid}/{tag} 

4. Dodanie tags dla notes:

PUT /users/{userid}/{noteid}/{tag} 

Zwracając się problemy z wydajnością, ściągam tags dla user powinien być szybki, bo masz na selektywną zbiórkę samo . Również obsługa duplikatów będzie prostsza, ponieważ możesz po prostu dodać podobne tags (przez id lub name) do tablicy related. Mam nadzieję, że to było pomocne.


Dlaczego nie zachować jako zagnieżdżone znaczniki własności

  • Konstrukcja nie jest tak skalowalny jak w poprzednim przypadku. Jeśli tags są zagnieżdżone i konieczna jest edycja tag lub konieczne jest dodanie niektórych informacji, będzie to wymagało zmian we wszystkich notes, ponieważ wiele notes może zawierać ten sam tag. Podczas utrzymywania tags jako zasobów, ten sam notes będzie mapowany z ich ids, a pojedyncza zmiana będzie wymagana w zbiorze/tabeli tags.

  • Obsługa duplikatu tags może nie być tak prosta, jak przy zachowaniu ich jako oddzielnych zasobów.

  • Podczas wyszukiwania tags należy wyszukać wszystkie tags osadzone wewnątrz każdego note. To dodaje obciążenie.


Jedyną zaletą korzystania tags jako zagnieżdżone nieruchomość IMO jest to będzie łatwiej dodawać lub usuwać tags dla konkretnego note.

+0

Zauważ, że w zależności od baz danych, możesz potrzebować [tablicy asocjacyjnej] (https://en.m.wikipedia.org/wiki/Associative_entity). –

+0

Jedna rzecz, której nie widzę w Twojej odpowiedzi, jest powodem wyboru jednego podejścia do drugiego. Dlaczego powinienem traktować tagi jako osobny zasób? –

+0

Dodałem jeszcze kilka punktów za używanie 'tagów' jako właściwości. Mam nadzieję, że teraz ma to więcej sensu. –

2

To może być nieco skomplikowane. Więc mogę po prostu podzielić się moim doświadczeniem z pracą Tag (w naszym przypadku była to główna cecha aplikacji VoIP).

W każdym razie wszystkie Tags będą jako unikatowy obiekt, który zawiera dużo informacji. Jak wiesz, byłoby to bardziej skomplikowane w przypadku przesyłania, ale potrzebujesz tych informacji, na przykład poniżej. I na pewno Json to najszybsze rozwiązanie.

type: 'notes', 
data: { 
    id: '123456789', 
    body: '...', 
    tags: [UUID1,UUID2,UUID3] 
} 

Tylko na przykład, ile informacji potrzebujesz. Gdy chcesz zmienić kolor znacznika lub rozmiaru, w oparciu o Współczynnik tagów, kolor oparty na użyciu numeru, połączony (nie to samo), duplikaty i tak dalej.

type: 'tag', 
data: { 
    uuid: '234-se-324', 
    body: 'superhero', 
    linked: [UUID3, UUID4] 
    rate: 4.6, 
    usage: 4323 
    duplicate: [superheros, suppahero] 
} 

Jak widać, używamy nawet duplikatów. Tylko po to, aby zapisać unikaty każdego Tag. Oczywiście, mamy również logikę do filtrowania Korzenia Słowa, ale jak widać na powyższym przykładzie, używamy również duplikatu ze specjalnymi Rootami, takimi jak "Superbohater" i "Suppanahero", które są dla nas takie same.

Może się wydawać, że jest to bardzo dużo informacji dla "autosugestów" lub "autouzupełniania", ale nigdy nie mieliśmy problemów z wydajnością (w przypadku, jeśli po stronie serwera wsparcie zaniknie). I wszystkie informacje są ważne dla każdego użycia, a także w tym przypadku Note.

+0

Dzięki za odpowiedź. Jedna rzecz, której nie widzę w twojej odpowiedzi, jest powodem wyboru jednego podejścia do drugiego. Dlaczego powinienem traktować tagi jako osobny zasób? –

1

Zapisywanie znaczników jako właściwości zagnieżdżonej ma sens, jeśli chcesz mieć wszystkie dane w tym samym wierszu. Dam ci przykład.

Na fakturze dodawania elementów,

Tytuł, opis, cena, ilosc, podatki, ...

podatkowy w tym przypadku może być: VAT 20%, dzięki czemu calcualte fakturę z 20%, ale Jednorazowa zmiana podatku na 22% i wszystkie faktury, które zostaną zapisane w DB, wzrosną o 2%. W takim przypadku dodajesz nową kolumnę i zapisujesz ją jako numer surowy 20, a gdy czytasz tę fakturę z db, otrzymujesz wszystkie dane z jednego wiersza, zamiast obliczać je z różnych tabel lub zmiennych.

To samo dotyczy tagów. Jeśli w jakiś sposób chcesz scalić duplikaty, łatwo jest zrobić to za pomocą identyfikatorów, a nie ciągów.

Istnieje również kilka innych czynników, które można rozważyć.

W sieci społecznościowej użytkownik może mieć tagi zwane umiejętnościami, zainteresowaniami, sportami i nie tylko.Nie ma prawdziwego sposób odróżnić tagów od (https://github.com/mbleigh/acts-as-taggable-on)

Więc jeśli robią znaczniki, które można oznaczyć wiele rzeczy trzeba wykorzystać atrybut id

Powiązane problemy