Dokumenty podrzędne Mongoose a schemat zagnieżdżony

122

Ciekawi mnie zalety i wady używania subdokumentów w porównaniu z głębszą warstwą w moim głównym schemacie:

var subDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [subDoc]
});

lub

var mainDoc = new Schema({
  names: [{
    name: String
 }]
});

Obecnie używam subdoców wszędzie, ale zastanawiam się przede wszystkim nad problemami z wydajnością lub zapytaniami, które mogę napotkać.

cyberwombat
źródło
Próbowałem ci odpowiedzieć na to pytanie, ale nie mogłem znaleźć sposobu. Ale spójrz tutaj: mongoosejs.com/docs/subdocs.html
gustavohenke
Oto dobra odpowiedź na pytania dotyczące MongoDB, aby zadać sobie pytanie podczas tworzenia schematu bazy danych: stackoverflow.com/questions/5373198/ ...
anthonylawson
Miałeś na myśli, że wymagane jest również opisanie _idpola? To znaczy, nie jest to trochę automatyczne, jeśli jest włączone?
Vadorequest
ktoś wie, czy _iddziedzina poddokumentów jest wyjątkowa? (utworzony metodą 2nd way w pytaniu OP)
Saitama

Odpowiedzi:

72

Według dokumentacji jest dokładnie to samo. Jednak użycie schematu spowodowałoby również dodanie _idpola (o ile nie zostało to wyłączone) i prawdopodobnie wykorzystuje więcej zasobów do śledzenia subdokumentów.

Alternatywna składnia deklaracji

Nowość w wersji 3 Jeśli nie potrzebujesz dostępu do instancji schematu dokumentu podrzędnego, możesz także zadeklarować dokumenty podrzędne, przekazując po prostu literał obiektu [...]

AndyL
źródło
1
Ale próbowałem tego. Dlaczego dane z dokumentów podrzędnych nie są przechowywane w oddzielnej kolekcji. Zawsze jest przechowywany w kolekcji mainDoc.
Fizer Khan
17
tak działają dokumenty podrzędne. są osadzane w dokumencie. zanim zaczniesz grać z Mongoose, upewnij się, że rozumiesz podstawową bazę danych MongoDB.
AndyL
1
Jeśli chodzi o dodanie do schematu _id, ma to sens, ale stworzyłem schemat z tablicą pod-docs i tablicą literałów obiektowych i _id został dodany do obu. Czy zachowanie się zmieniło?
Drew Goodwin
@DrewGoodwin wygląda na to, że tak było przez jakiś czas: stackoverflow.com/questions/17254008/…
cheesemacfly
37

Jeśli masz schematy, które są ponownie używane w różnych częściach modelu, przydatne może być zdefiniowanie indywidualnych schematów dla dokumentów podrzędnych, aby nie trzeba było się powielać.

sonstone
źródło
4
To świetna odpowiedź. Czasami używam dokumentów podrzędnych w więcej niż jednym modelu lub mam dwa pola w modelu, które wymagają rozróżnienia, ale nadal mają taką samą strukturę dokumentu podrzędnego.
Martin Hallén
2
należy również wziąć pod uwagę zalety / wady zapisywania zbędnych informacji.
Sam Vloeberghs
25

Z dokumentów osadzonych należy korzystać, jeśli są to dokumenty statyczne lub nie więcej niż kilkaset ze względu na wpływ na wydajność. Omówiłem ten problem już jakiś czas temu. Niedawno Asya Kamsky, która pracuje jako architekt rozwiązań dla MongoDB, napisała artykuł o „używaniu subdokumentów”.

Mam nadzieję, że pomoże to komuś, kto szuka rozwiązań lub najlepszych praktyk.

Oryginalny post na http://askasya.com/post/largeembeddedarrays . Możesz przejść do jej profilu stackoverflow na https://stackoverflow.com/users/431012/asya-kamsky

Przede wszystkim musimy zastanowić się, dlaczego mielibyśmy chcieć coś takiego zrobić. Zwykle radziłbym ludziom osadzać rzeczy, które zawsze chcą odzyskać, gdy pobierają ten dokument. Drugą stroną tego jest to, że nie chcesz osadzać w dokumencie rzeczy, których nie chcesz odzyskać.

Jeśli umieścisz w dokumencie aktywność, którą wykonuję, na początku będzie ona działać świetnie, ponieważ cała moja aktywność jest właśnie tam, a po jednym przeczytaniu możesz odzyskać wszystko, co chcesz mi pokazać: „ostatnio kliknąłeś to i tutaj czy twoje ostatnie dwa komentarze ”, ale co się dzieje po sześciu miesiącach i nie obchodzą mnie rzeczy, które zrobiłem dawno temu i nie chcesz mi ich pokazywać, chyba że specjalnie poszukam jakiejś starej aktywności?

Po pierwsze, w końcu będziesz zwracać coraz większy dokument i dbać o coraz mniejszą jego część. Ale możesz użyć projekcji, aby zwrócić tylko część tablicy, prawdziwym problemem jest to, że dokument na dysku stanie się większy i nadal będzie czytany, nawet jeśli zamierzasz zwrócić tylko część tego użytkownikowi końcowemu, ale ponieważ moja działalność nie ustanie tak długo, jak długo będę aktywny, dokument będzie się rozrastał.

Najbardziej oczywistym problemem jest to, że w końcu osiągniesz limit 16 MB dokumentów, ale wcale nie powinieneś się tym martwić. Dokument, który stale rośnie, będzie generował coraz wyższe koszty za każdym razem, gdy będzie musiał zostać przeniesiony na dysk, a nawet jeśli podejmiesz kroki w celu złagodzenia skutków fragmentacji, twoje zapisy będą ogólnie niepotrzebnie długie, wpływając na ogólną wydajność całej aplikacji.

Jest jeszcze jedna rzecz, którą możesz zrobić, która całkowicie zniszczy wydajność aplikacji, a jest to indeksowanie tej stale rosnącej tablicy. Oznacza to, że za każdym razem, gdy dokument z tą tablicą jest przenoszony, liczba pozycji indeksu, które wymagają aktualizacji, jest wprost proporcjonalna do liczby indeksowanych wartości w tym dokumencie, a im większa tablica, tym większa będzie ta liczba. być.

Nie chcę, aby to odstraszyło Cię przed używaniem tablic, gdy są one dobrze dopasowane do modelu danych - są potężną funkcją modelu danych bazy danych dokumentów, ale podobnie jak wszystkie potężne narzędzia muszą być używane w odpowiednich okolicznościach i należy go używać ostrożnie.

efkan
źródło
3
To powinna być najlepsza odpowiedź; to huk na pieniądze. Własne białe księgi MongoDB mówią prawie to samo.
Jay Edwards
Ten artykuł o wzorze wiadra jest komplementem, o którym ładnie mówi Asya. mongodb.com/blog/post/building-with-patterns-the-bucket-pattern Myślę, że schemat subDoc w pytaniu OP działałby dobrze ze wzorcem wiadra.
plong0
13

Zasadniczo utworzyć zmienną nestedDovi umieścić go tutajname: [nestedDov]

Prosta wersja:

var nestedDoc = new Schema({
  name: String
});

var mainDoc = new Schema({
  names: [nestedDoc]
});

Przykład JSON

{
    "_id" : ObjectId("57c88bf5818e70007dc72e85"),
    "name" : "Corinthia Hotel Budapest",
    "stars" : 5,
    "description" : "The 5-star Corinthia Hotel Budapest on the Grand Boulevard offers free access to its Royal Spa",
    "photos" : [
        "/photos/hotel/corinthiahotelbudapest/1.jpg",
        "/photos/hotel/corinthiahotelbudapest/2.jpg"
    ],
    "currency" : "HUF",
    "rooms" : [
        {
            "type" : "Superior Double or Twin Room",
            "number" : 20,
            "description" : "These are some great rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/2.jpg",
                "/photos/room/corinthiahotelbudapest/5.jpg"
            ],
            "price" : 73000
        },
        {
            "type" : "Deluxe Double Room",
            "number" : 50,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 92000
        },
        {
            "type" : "Executive Double Room",
            "number" : 25,
            "description" : "These are amazing rooms",
            "photos" : [
                "/photos/room/corinthiahotelbudapest/4.jpg",
                "/photos/room/corinthiahotelbudapest/6.jpg"
            ],
            "price" : 112000
        }
    ],
    "reviews" : [
        {
            "name" : "Tamas",
            "id" : "/user/tamas.json",
            "review" : "Great hotel",
            "rating" : 4
        }
    ],
    "services" : [
        "Room service",
        "Airport shuttle (surcharge)",
        "24-hour front desk",
        "Currency exchange",
        "Tour desk"
    ]
}

Przykład:

wprowadź opis obrazu tutaj

Wayne Chiu
źródło
1
To w ogóle nie dotyczy kwestii wydajności.
cyberwombat
Trochę zredagowałem, żeby mieć więcej sensu. Co myślisz?
Wayne Chiu
3
Pytanie nie dotyczy sposobu wykonywania zagnieżdżonych schematów. Jest to dyskusja na temat tego, czy Mongoose jest bardziej wydajny z zagnieżdżonymi schematami lub osadzonymi dokumentami podrzędnymi. Zasadniczo mówimy o testach porównawczych, rodzajach lub przypadkach skrajnych, w których Mongoose woli jeden od drugiego. I jak wspomina wybrana odpowiedź, wydaje się, że nie ma to żadnego znaczenia, przynajmniej od wersji V3.
cyberwombat
17
Może nie działa w przypadku OP, ale uznałem to za bardzo pomocne. Dzięki.
Gene Higgins,
Jest to dobre, gdy wszystkie 3 schematy są zadeklarowane w jednym pliku .js, jak możemy sobie z tym poradzić, gdy są zadeklarowane w 3 różnych plikach .js?
Satyam
9

Myślę, że jest to obsługiwane w innym miejscu przez wiele postów na SO.

Tylko kilka:

Najważniejsze jest to, że nie ma tutaj jednej odpowiedzi, a jedynie zestaw dość złożonych kompromisów.

Gates VP
źródło
3
Być może nie formułuję poprawnie mojego pytania - to nie jest kwestia tego, jak powinienem ustrukturyzować moją bazę danych, ale raczej wewnętrzne aspekty korzystania z podschematu, a nie tylko zapisywania tablicy w głębszej warstwie. Moim głównym powodem korzystania z podschematu jest to, że mogę używać niestandardowych typów schematów i zlecać im walidację - coś, co nie działa z zagnieżdżonymi tablicami (z poprzedniego pytania, które miałem na SO). O ile wiem, subdoc jest prawie tym samym, co tablica zagnieżdżona - po prostu nie znam jej elementów wewnętrznych - jeśli ich użycie spowodowałoby problemy z wydajnością lub takie.
cyberwombat
0

Jest między nimi pewna różnica:

  • Korzystanie ze schematu zagnieżdżonego jest pomocne przy sprawdzaniu poprawności.

  • Schemat zagnieżdżony można ponownie wykorzystać w innych schematach.

  • Schemat zagnieżdżony dodaje pole „_id” do dokumentu podrzędnego, chyba że użyto „_id: false”
Ahmad Zahabi
źródło