MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Dlaczego Mongoose ma zarówno schematy, jak i modele?

EDYTUJ: Chociaż było to przydatne dla wielu osób, jak wspomniano w komentarzach, odpowiada raczej „jak”, a nie dlaczego. Na szczęście odpowiedź na pytanie została udzielona również w innym miejscu, z tą odpowiedzią na inne pytanie. Zostało to od pewnego czasu połączone w komentarzach, ale zdaję sobie sprawę, że wielu może nie zajść tak daleko podczas czytania.

Często najłatwiejszym sposobem odpowiedzi na tego typu pytanie jest podanie przykładu. W tym przypadku ktoś już to za mnie zrobił :)

Spójrz tutaj:

http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/

EDYTUJ: Oryginalny post (jak wspomniano w komentarzach) wydaje się już nie istnieć, więc odtwarzam go poniżej. Jeśli kiedykolwiek wróci lub właśnie się przeniósł, daj mi znać.

Daje przyzwoity opis używania schematów w modelach w manguście i dlaczego chcesz to zrobić, a także pokazuje, jak przekazywać zadania przez model, podczas gdy schemat dotyczy całej struktury itp.

Oryginalny post:

Zacznijmy od prostego przykładu osadzenia schematu w modelu.

var TaskSchema = new Schema({
    name: String,
    priority: Number
});
 
TaskSchema.virtual('nameandpriority')
    .get( function () {
        return this.name + '(' + this.priority + ')';
    });
 
TaskSchema.method('isHighPriority', function() {
    if(this.priority === 1) {
        return true;
    } else {
        return false;
    }
}); 
 
var ListSchema = new Schema({
    name: String,
    tasks: [TaskSchema]
});
 
mongoose.model('List', ListSchema);
 
var List = mongoose.model('List');
 
var sampleList = new List({name:'Sample List'});

Utworzyłem nowy TaskSchema obiekt z podstawowymi informacjami, jakie może mieć zadanie. Atrybut wirtualny Mongoose jest skonfigurowany tak, aby wygodnie łączyć nazwę i priorytet zadania. Określiłem tutaj tylko getter, ale obsługiwane są również wirtualne setery.

Zdefiniowałem również prostą metodę zadania o nazwie isHighPriority aby zademonstrować, jak metody działają z tą konfiguracją.

W ListSchema definicję zauważysz, jak tasks klucz jest skonfigurowany do przechowywania tablicy TaskSchema przedmioty. task klucz stanie się instancją DocumentArray który zapewnia specjalne metody radzenia sobie z osadzonymi dokumentami Mongo.

Na razie przekazałem tylko ListSchema obiekt do mongoose.model i opuścił TaskSchema na zewnątrz. Z technicznego punktu widzenia nie jest konieczne włączanie TaskSchema w formalny model, ponieważ nie będziemy go przechowywać w jego własnej kolekcji. Później pokażę ci, jak to niczego nie zaszkodzi, jeśli to zrobisz, i może pomóc uporządkować wszystkie modele w ten sam sposób, zwłaszcza gdy zaczynają one obejmować wiele plików.

Z List konfiguracja modelu dodajmy do niego kilka zadań i zapiszmy je w Mongo.

var List = mongoose.model('List');
var sampleList = new List({name:'Sample List'});
 
sampleList.tasks.push(
    {name:'task one', priority:1}, 
    {name:'task two', priority:5}
);
 
sampleList.save(function(err) {
    if (err) {
        console.log('error adding new list');
        console.log(err);
    } else {
        console.log('new list successfully saved'); 
    }
});

Atrybut zadań w wystąpieniu naszej List model (sampleList ) działa jak zwykła tablica JavaScript i możemy dodawać do niej nowe zadania za pomocą push. Ważną rzeczą do zauważenia są tasks są dodawane jako zwykłe obiekty JavaScript. To subtelne rozróżnienie, które może nie być od razu intuicyjne.

Możesz sprawdzić w powłoce Mongo, że nowa lista i zadania zostały zapisane w Mongo.

db.lists.find()
{ "tasks" : [
    {
        "_id" : ObjectId("4dd1cbeed77909f507000002"),
        "priority" : 1,
        "name" : "task one"
    },
    {
        "_id" : ObjectId("4dd1cbeed77909f507000003"),
        "priority" : 5,
        "name" : "task two"
    }
], "_id" : ObjectId("4dd1cbeed77909f507000001"), "name" : "Sample List" }

Teraz możemy użyć ObjectId aby wyświetlić Sample List i powtarzaj swoje zadania.

List.findById('4dd1cbeed77909f507000001', function(err, list) {
    console.log(list.name + ' retrieved');
    list.tasks.forEach(function(task, index, array) {
        console.log(task.name);
        console.log(task.nameandpriority);
        console.log(task.isHighPriority());
    });
});

Jeśli uruchomisz ten ostatni fragment kodu, pojawi się błąd informujący, że osadzony dokument nie ma metody isHighPriority . W obecnej wersji Mongoose nie masz bezpośredniego dostępu do metod na osadzonych schematach. Istnieje otwarte zgłoszenie, aby to naprawić, a po zadaniu pytania grupie dyskusyjnej Mongoose, manimal45 opublikował przydatne obejście problemu, z którego można skorzystać na razie.

List.findById('4dd1cbeed77909f507000001', function(err, list) {
    console.log(list.name + ' retrieved');
    list.tasks.forEach(function(task, index, array) {
        console.log(task.name);
        console.log(task.nameandpriority);
        console.log(task._schema.methods.isHighPriority.apply(task));
    });
});

Jeśli uruchomisz ten kod, powinieneś zobaczyć następujące dane wyjściowe w wierszu poleceń.

Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false

Mając to na uwadze, zmieńmy TaskSchema w model Mongoose.

mongoose.model('Task', TaskSchema);
 
var Task = mongoose.model('Task');
 
var ListSchema = new Schema({
    name: String,
    tasks: [Task.schema]
});
 
mongoose.model('List', ListSchema);
 
var List = mongoose.model('List');

TaskSchema definicja jest taka sama jak wcześniej, więc ją pominąłem. Po przekształceniu w model nadal możemy uzyskać dostęp do podstawowego obiektu Schema za pomocą notacji kropkowej.

Utwórzmy nową listę i osadźmy w niej dwie instancje modelu zadań.

var demoList = new List({name:'Demo List'});
 
var taskThree = new Task({name:'task three', priority:10});
var taskFour = new Task({name:'task four', priority:11});
 
demoList.tasks.push(taskThree.toObject(), taskFour.toObject());
 
demoList.save(function(err) {
    if (err) {
        console.log('error adding new list');
        console.log(err);
    } else {
        console.log('new list successfully saved'); 
    }
});

Ponieważ osadzamy instancje modelu zadań na liście, wywołujemy toObject na nich, aby przekonwertować ich dane na zwykłe obiekty JavaScript, które List.tasks DocumentArray oczekuje. Gdy zapiszesz instancje modelu w ten sposób, Twoje osadzone dokumenty będą zawierać ObjectIds .

Pełny przykład kodu jest dostępny jako sedno. Mam nadzieję, że te obejścia pomogą wygładzić sytuację, gdy Mongoose nadal się rozwija. Nadal jestem całkiem nowy w Mongoose i MongoDB, więc zachęcam do dzielenia się lepszymi rozwiązaniami i wskazówkami w komentarzach. Miłego modelowania danych!



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Agregacja $ lookup nie zwraca elementów oryginalnej kolejności tablicy

  2. Obsługa niestandardowego marszałkowania BSON

  3. Tworzenie, odczytywanie, aktualizowanie i usuwanie danych przy użyciu Node.js — Mongoose

  4. Mongodb:Nie udało się połączyć z 127.0.0.1:27017, powód:errno:10061

  5. MongoDB $rok