W MongoDB unikalny indeks zapewnia, że określona wartość w polu nie występuje w więcej niż jednym dokumencie. nie gwarantuje, że wartość jest unikalna w całej tablicy w jednym dokumencie. Jest to wyjaśnione tutaj w Podręczniku MongoDB, gdzie omawia on unikalne indeksy wielokluczowe.
W ten sposób unikalny indeks nie spełni Twoich wymagań. Zapobiegnie to zawieraniu zduplikowanych kombinacji w oddzielnych dokumentach, ale nadal pozwoli, aby pojedynczy dokument zawierał zduplikowane wartości w tablicy.
Najlepszą opcją jest zmiana modelu danych tak, aby podzielić tablicę obiektów technologyEmployeeRef na oddzielne dokumenty. Podzielenie go na osobne dokumenty pozwoli ci użyć unikalnego indeksu, aby wymusić unikalność.
Konkretna implementacja, która powinna zostać zastosowana w przypadku tej zmiany modelu danych, będzie zależeć od wzorca dostępu (który jest poza zakresem tego pytania).
Jednym ze sposobów, w jaki można to zrobić, jest utworzenie kolekcji TechnologyEmployee zawierającej wszystkie pola, które obecnie istnieją w tablicy technologyEmployeeRef. Dodatkowo ta kolekcja TechnologyEmployee miałaby pole, takie jak e-mail, które umożliwiłoby powiązanie go z dokumentem w kolekcji Employee.
Przykładowy dokument pracownika
{
....
....
"firstName" : "John",
"lastName" : "Doe",
"email" : "[email protected]",
.....
.....
.....
}
Przykładowy dokument dotyczący technologii pracownika
{
"email" : "[email protected]",
"technologyCd" : "Java",
"technologyName" : "Java8",
....
.....
"status" : "A"
}
Indeks w kolekcji EmployeeTechnology
{'email' : 1, 'technologyCd' : 1}, {unique: true}
Wadą tego podejścia jest to, że aby mieć wszystkie dane, trzeba by czytać z dwóch kolekcji. Ta wada może nie być wielkim problemem, jeśli rzadko musisz pobierać dane z obu kolekcji jednocześnie. Jeśli potrzebujesz wszystkich danych, możesz je przyspieszyć za pomocą indeksów. Dzięki indeksom można by to przyspieszyć poprzez użycie objętych zapytań.
Inną opcją jest denormalizacja danych. Możesz to zrobić, duplikując dane pracownika, do których musisz uzyskać dostęp w tym samym czasie, co dane technologii.
Przykładowe dokumenty
[
{
....
"firstName" : "John",
"lastName" : "Doe",
"email" : "[email protected]",
.....
"technologyCd" : "Java",
"technologyName" : "Java8",
....
"status" : "A"
},
{
....
"firstName" : "John",
"lastName" : "Doe",
"email" : "[email protected]",
.....
"technologyCd" : "Spring",
"technologyName" : "Spring Boot2",
....
"status" : "A"
}
]
W tym poście na blogu MongoDB mówią, że
Można to zrobić tylko w przypadku pól, które są często odczytywane, odczytywane są znacznie częściej niż są aktualizowane i gdzie nie jest wymagana silna spójność, ponieważ aktualizowanie zdenormalizowanej wartości jest wolniejsze, droższe i nie jest niepodzielne.
Lub, jak już wspomniałeś, sensowne może być pozostawienie modelu danych bez zmian i sprawdzenie unikalności po stronie aplikacji. Może to prawdopodobnie zapewnić najlepszą wydajność odczytu, ale ma pewne wady. Po pierwsze, spowolni to operacje zapisu, ponieważ aplikacja będzie musiała przeprowadzić pewne testy, zanim będzie mogła zaktualizować bazę danych.
Może to mało prawdopodobne, ale istnieje również możliwość, że nadal możesz otrzymać duplikaty. Jeśli istnieją dwa równoległe żądania wstawienia tego samego obiektu EmployeeTechnology do tablicy, weryfikacja drugiego żądania może zakończyć się (i przejść), zanim pierwsze żądanie zostanie zapisane w bazie danych. Sam widziałem podobny scenariusz z aplikacją, nad którą pracowałem. Mimo że aplikacja sprawdzała wyjątkowość, jeśli użytkownik dwukrotnie kliknie przycisk przesyłania, w bazie danych pojawią się zduplikowane wpisy. W takim przypadku wyłączenie przycisku przy pierwszym kliknięciu drastycznie zmniejszyło ryzyko. To niewielkie ryzyko może być tolerowane, w zależności od Twoich wymagań i wpływu zduplikowanych wpisów.
Które podejście ma największy sens, w dużej mierze zależy od wzorca dostępu i wymagań. Mam nadzieję, że to pomoże.