Wręcz przeciwnie, rozwiązanie 1 i 2 to najlepszy wybór. Rozwiązanie 3 można rozważyć, gdy częstotliwość aktualizacji/tworzenia jest bardzo mniejsza w porównaniu z częstotliwością odczytu projektów i użytkowników, ponieważ nawet aktualizacja/tworzenie wymaga dwóch zapytań, ale łatwość odczytu będzie nadrabiać.
Aby wybrać rozwiązanie 1 i 2, należy wziąć pod uwagę częstotliwości odczytu. Czy będziesz częściej potrzebował projektów użytkownika, czy też zastosowań projektu i wybieraj zgodnie z tym. Jeśli uważasz, że oba mają stosunkowo tę samą częstotliwość, lepiej jest utrzymywać obiekt użytkownika w jak najmniejszej liczbie klastrów. Niezależnie od wybranej opcji rozważ zachowanie index
na tablicy przechowującej _id
s (projektów lub użytkowników).
Na przykład
userSchema = new Schema(
{//otherstuff
project_ids: [{type: Schema.Types.ObjectId, ref: 'Project'}})
...
})
userSchema.index({'project_ids':1})
lub
projectSchema = new Schema(
{//otherstuff
user_ids: [{type: Schema.Types.ObjectId, ref: 'User'}})
...
})
projectSchema.index({'user_ids':1})
Utrzymywanie indeksu w tablicy _id
znacznie poprawi szybkość zapytań po stronie, na której obawiasz się, że wystąpią znaczne koszty ogólne.
Ale zachowaj index
tylko wtedy, gdy ta relacja jest ważną relacją z wieloma zapytaniami. Jeśli jest to tylko uboczna funkcja twojego projektu, możesz zrobić without
indeks też.
Jeśli użytkownik może robić wiele rzeczy i ma wiele relacji, będziesz potrzebować tego obiektu użytkownika stale w całej aplikacji, więc jeśli Twoja aplikacja nie jest specyficzna dla projektu, lepiej nie umieszczać identyfikatorów projektu w schemacie użytkownika . Ale ponieważ tylko umieszczamy identyfikatory, i tak nie jest to zbyt duże obciążenie. Nie musisz się o to martwić.
Indeks reg na obu tablicach:Tak, oczywiście. Ale kiedy wybierasz rozwiązanie 3, wcale nie potrzebujesz indeksu, ponieważ nie będziesz wykonywać zapytania, aby uzyskać listę projektów użytkownika lub listę użytkowników w projekcie. Rozwiązanie 3 sprawia, że czytanie jest bardzo łatwe, ale pisanie trochę kłopotliwe. Ale jak wspomniałeś, twój przypadek użycia obejmuje reading>>writing
, wybierz rozwiązanie 3, ale zawsze istnieje ryzyko niespójności danych, którą musisz się zająć.
Indeksowanie po prostu przyspiesza. Przejrzyj dokumenty i poszukaj googlarstwa. Nic fajnego. Wykonywanie zapytań przez tablice indeksowane jest wydajne niż normalne tablice. Na przykład Załóżmy, że używasz rozwiązania 2. Zapisz identyfikatory projektu w polu project_ids.
Możesz łatwo uzyskać projekty użytkownika. To jest proste.
Ale żeby zdobyć użytkowników project1. Potrzebujesz takiego zapytania.
User.find({project_ids:project._id},function(err,docs){
//here docs will be the list of the users of project1
})
//The above query might be slow if the user base is large.
//But it can be improved vastly by indexing the project_ids field in the User schema.
Podobnie dla rozwiązania 1. Każdy projekt ma pole user_ids. Załóżmy, że mamy użytkownika 1. Aby uzyskać projekty użytkownika, wykonujemy następujące zapytanie
Project.find({user_ids:user1._id},function(err,docs){
//here docs will be the projects of user1
//But it can be improved vastly by indexing the user_ids field in the Project schema.
Jeśli zastanawiasz się nad rozwiązaniem 1 w porównaniu z rozwiązaniem 2, rozwiązanie 1 jest chyba lepsze. Mogą wystąpić przypadki, w których potrzebujesz użytkownika bez jego projektów, ale szanse na wymaganie projektu bez użytkowników są dość niskie. Ale to zależy od konkretnego przypadku użycia.