{"id":496,"date":"2018-06-26T22:55:24","date_gmt":"2018-06-26T22:55:24","guid":{"rendered":"https:\/\/www.wpvs.de\/iot-2018\/?p=496"},"modified":"2021-05-14T10:07:03","modified_gmt":"2021-05-14T08:07:03","slug":"raspberrybuy-7-mongodb-mongoose-typegoose","status":"publish","type":"post","link":"https:\/\/www.iot-embedded.de\/iot-2018\/projekt-raspberrybuy\/raspberrybuy-7-mongodb-mongoose-typegoose\/","title":{"rendered":"RaspberryBuy (7) \u2013 MongoDB, Mongoose, Typegoose"},"content":{"rendered":"<h1>Datenmodellierung<\/h1>\n<p>In diesem Blog soll es um die Dokumenten-orientierte Datenmodellierung in der MongoDB und den lesenden und schreibenden Zugriff auf diese Daten gehen.<\/p>\n<p>Unser urspr\u00fcngliches, normalisiertes relationales Datenmodell sah wie folgt aus:<\/p>\n<p><a href=\"http:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/ER_diagram.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-497\" src=\"http:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/ER_diagram-300x96.png\" alt=\"\" width=\"830\" height=\"265\" srcset=\"https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/ER_diagram-300x96.png 300w, https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/ER_diagram-1024x328.png 1024w, https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/ER_diagram-768x246.png 768w, https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/ER_diagram.png 1163w\" sizes=\"(max-width: 830px) 100vw, 830px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Fachlich wurde diese Modellierung jedoch noch ge\u00e4ndert. Die <em>n:m<\/em> Beziehung zwischen einem Profil und dem Bestand (realisiert mit der Relation <em>ProfileStock<\/em>) ist nicht notwendig. Stattdessen ist der Bestand entweder einem Profil zugeordnet (Attribut <em>owner<\/em>) oder wird von allen Profilen geteilt (Attribut <em>shared<\/em>). Des Weiteren hat die Entit\u00e4t <em>Profil<\/em> ein optionales Attribut <em>image<\/em>, welches f\u00fcr das Profilbild verwendet wird.<\/p>\n<p>Wie bereits in vorherigen Blog-Beitr\u00e4gen erl\u00e4utert, haben wir uns dazu entschieden, eine MongoDB zu benutzen. Dies ist die meist verbreitete NoSQL Datenbank. Im Gegensatz zu einer SQL Datenbank ist kein fixes Datenschema erforderlich. Die Daten werden in folgenden Strukturen gespeichert:<\/p>\n<ul>\n<li>Collection: Sammlung von Dokumenten, \u00e4hnlich einer SQL-Tabelle<\/li>\n<li>Dokument: Objektinstanz mit verschiedenen Attributen, \u00e4hnlich einer Tabellenzeile in SQL. Ein MongoDB Dokument kann jedoch beliebig tief sein (Subdokumente) und auch Arrays als Attribute besitzen. Jedes Dokument kann anders aussehen, da kein Schema definiert ist.<\/li>\n<\/ul>\n<p>F\u00fcr die MongoDB ist daher kein normalisiertes Datenmodell notwendig. Im Gegenteil, Subdokumente und Arrays sind sogar erw\u00fcnscht. Daten, die zusammengeh\u00f6ren, sollen ohne Joins schnell und einfach gelesen werden. Die Modellierung wird dadurch komplexer, da viele unterschiedliche M\u00f6glichkeiten bestehen, wie die Daten abgebildet werden. Wichtigster Anhaltspunkt ist bereits in dieser fr\u00fchen Phase der Entwicklung die Modellierung der notwendigen Datenabfragen. Ziel ist es, das relationale Modell so zu denormalisieren, dass die Performance von Datenabfragen optimiert wird. Folgende Punkte sollten dabei ber\u00fccksichtigt werden:<\/p>\n<ul>\n<li>Die Dokumententiefe (eingebettete Subdokumente) sollte nicht zu tief sein, da beim Lesen eines Dokumentes immer das gesamte Dokument gelesen wird<\/li>\n<li>Zusammengeh\u00f6rende Daten schon beim Schreiben der Daten joinen<\/li>\n<li>Datenduplikate sind in gewissem Rahmen erlaubt<\/li>\n<\/ul>\n<p>Die folgende Abbildung zeigt unsere dokumentenorientierte Modellierung. Wie zu sehen ist, sind nur zwei Collections notwendig. Die Dokumente der Collection \u201eUser\u201c beinhalten auch alle Profile des Users, genauso wie die Produkt-Dokumente alle Best\u00e4nde beinhalten.<\/p>\n<p><a href=\"http:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/mongo_modellierung.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-500\" src=\"http:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/mongo_modellierung-300x167.png\" alt=\"\" width=\"613\" height=\"341\" srcset=\"https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/mongo_modellierung-300x167.png 300w, https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/06\/mongo_modellierung.png 685w\" sizes=\"(max-width: 613px) 100vw, 613px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h1>Datenzugriff<\/h1>\n<p>In einer der letzten Semester haben wir bereits die Java Persistence API kennengelernt. Dies ist ein Objekt-Relationaler-Mapper (ORM), der den Zugriff auf die Datenbank stark vereinfacht. Die DB-Tabellen werden dabei auf Java Klassen und Objekte gemappt. Mithilfe von Annotationen kann das Mapping konfiguriert werden. F\u00fcr die MongoDB existiert mit der <a href=\"http:\/\/mongoosejs.com\/\">Mongoose<\/a> Library ein \u00e4hnliches Framework. Dies wird als Object-Document-Mapper bezeichnet (ODM). Mithilfe eines definierten Models wird der Zugriff auf die Datenbank vereinfacht. Models entsprechen Klassen, deren Instanzen beispielsweise die Methode <em>save<\/em> besitzen, um ein zugeh\u00f6riges Dokument in der DB zu erstellen. So k\u00f6nnen die Vorteile einer NoSQL Datenbank mit den Vorteilen eines Datenschemas kombiniert werden.<\/p>\n<p>Bei der Verwendung von Typescript zusammen mit Mongoose sind wir dabei jedoch auf ein Problem gesto\u00dfen. Unsere Datenobjekte mussten doppelt definiert werden, einmal in Form einer Typescript Klasse zum Nutzen der Typisierungsm\u00f6glichkeiten und noch einmal zum Definieren der Mongoose-Model.<\/p>\n<p>Nach kurzer Recherche sind wir auf <a href=\"https:\/\/github.com\/szokodiakos\/typegoose\">Typegoose<\/a> gesto\u00dfen. Dies ist ein npm-Paket, welches zum Ziel hat, das oben genannte Problem zu l\u00f6sen. Dabei wird nur die TS Klasse definiert und, \u00e4hnlich wie bei der JPA, um Annotationen erweitert. Wichtig sind hier die Annotationen @prop (normales Attribut) und @arrayProp\u00a0(Array-Attribut). Auch Referenzen auf andere Dokumente (\u00fcber die Dokument-ID) sind m\u00f6glich. Mithilfe von Vererbung wird f\u00fcr jede Klasse eine Methode\u00a0<em>getModelForClass<\/em> bereitgestellt, welche f\u00fcr die Klasse das dazugeh\u00f6rige Mongoose-Model zur\u00fcckgibt. Ein Beispiel f\u00fcr eine solche Klasse mit Annotationen ist bereits in der obigen Abbildung zu sehen gewesen.<\/p>\n<p>Zusammenfassend ist aus unserer Sicht eine MongoDB gut geeignet, wenn Entit\u00e4ten oft gemeinsam gelesen werden, dies im Voraus bereits ersichtlich ist und keine gro\u00dfen \u00c4nderungen im Funktionsumfang der Anwendung mehr erwartet werden.<\/p>\n<p>Weitere Infos: <a href=\"https:\/\/www.tutorialspoint.com\/mongodb\/mongodb_data_modeling.htm\">https:\/\/www.tutorialspoint.com\/mongodb\/mongodb_data_modeling.htm<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Datenmodellierung In diesem Blog soll es um die Dokumenten-orientierte Datenmodellierung in der MongoDB und den lesenden und schreibenden Zugriff auf diese Daten gehen. Unser urspr\u00fcngliches, normalisiertes relationales Datenmodell sah wie folgt aus: &nbsp; Fachlich wurde diese Modellierung jedoch noch ge\u00e4ndert.<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/posts\/496"}],"collection":[{"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/comments?post=496"}],"version-history":[{"count":1,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/posts\/496\/revisions"}],"predecessor-version":[{"id":645,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/posts\/496\/revisions\/645"}],"wp:attachment":[{"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/media?parent=496"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/categories?post=496"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/tags?post=496"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}