MongoDB

MongoDB ist die führende Open-Source, Document Datenbank die für einfache Entwicklung und Skalierung aber auch für Big Data Szenarien entwickelt wurde.

Java und MongoDB - Dokumente erstellen

Marc-David Militz
Expert
  • Artikel von Maxime Beugnet

    • englischer Originalartikel
      https://www.mongodb.com/blog/post/quick-start-mongodb-and-java--creating-documents
      Übersetzung mit freundlicher Genehmigung von MongoDB


      In einem früheren Blog-Beitrag haben wir Ihnen gezeigt, wie Sie MongoDB und Java verbinden und eine sehr einfache Abfrage durchführen.
      https://www.qualiero.com/community/mongodb/mongodb-theorie/java-und-mongodb-start-und-setup.html
      In diesem Blogbeitrag zeige wir Ihnen, wie Sie Dokumente in MongoDB einfügen.

      • Vorbereitungen

        • Ich werde das gleiche Repository verwenden, dass wir im vorherigen Blog-Beitrag verwendet habe. Wenn Sie noch keine Kopie davon haben, können Sie sie klonen:
          git clone https://github.com/mongodb-developer/java-quick-start

          Wenn Sie dieses Repository bereits geklont haben, stellen Sie sicher, dass Sie die aktuellste Version verwenden:
          git pull

          Im vorherigen Blogbeitrag haben wir die Klassen "HelloMongoDB" und "Connection" erstellt. Dieses Mal arbeiten wir an der Klasse "Create".
          Wenn Sie noch keinen kostenlosen Cluster in MongoDB Atlas eingerichtet haben, ist jetzt der richtige Zeitpunkt dafür. Sie bekommen alle Informationen dazu in diesem Blog-Beitrag.
          https://www.mongodb.com/blog/post/quick-start-getting-your-free-mongodb-atlas-cluster

          • Überprüfen der Collection und des Datenmodells

            • Im Beispieldatensatz finden Sie die Datenbank "sample_training", die eine Collection mit Benotungen enthält. Jedes Dokument in dieser Sammlung repräsentiert die Noten eines Schülers für eine bestimmte Klasse.
              Hier ist die JSON-Darstellung eines Dokuments in der Mongo Shell.
              MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.grades.findOne({student_id: 0, class_id: 339})
              {
              "_id" : ObjectId("56d5f7eb604eb380b0d8d8ce"),
              "student_id" : 0,
              "scores" : [
              {
              "type" : "exam",
              "score" : 78.40446309504266
              },
              {
              "type" : "quiz",
              "score" : 73.36224783231339
              },
              {
              "type" : "homework",
              "score" : 46.980982486720535
              },
              {
              "type" : "homework",
              "score" : 76.67556138656222
              }
              ],
              "class_id" : 339
              }

              Und hier ist die erweiterte JSON-Darstellung desselben Schülers. Sie können es in MongoDB Compass abrufen, wenn Sie möchten.
              Extended JSON ist die lesbare Version eines BSON-Dokuments ohne Verlust von Typinformationen. Weitere Informationen zum Java-Treiber und zu BSON finden Sie hier.
              https://mongodb.github.io/mongo-java-driver/3.11/bson/extended-json/
              {
              "_id": {
              "$oid": "56d5f7eb604eb380b0d8d8ce"
              },
              "student_id": {
              "$numberDouble": "0"
              },
              "scores": [{
              "type": "exam",
              "score": {
              "$numberDouble": "78.40446309504266"
              }
              }, {
              "type": "quiz",
              "score": {
              "$numberDouble": "73.36224783231339"
              }
              }, {
              "type": "homework",
              "score": {
              "$numberDouble": "46.980982486720535"
              }
              }, {
              "type": "homework",
              "score": {
              "$numberDouble": "76.67556138656222"
              }
              }],
              "class_id": {
              "$numberDouble": "339"
              }
              }

              Wie Sie sehen, speichert MongoDB BSON-Dokumente und für jedes Schlüssel-Wert-Paar enthält das BSON den Schlüssel und den Wert zusammen mit seinem Typ.
              Auf diese Weise weiß MongoDB, dass "class_id" tatsächlich ein Double und keine Ganzzahl ist, was in der Mongo Shell-Darstellung dieses Dokuments nicht explizit angegeben ist.

              Wir haben bereits 10.000 Schüler ("student_id" von 0 bis 9999) in dieser Collection und jeder von ihnen hat 10 verschiedene Klassen belegt, was zu 100.000 Dokumenten in dieser Collection führt.
              Angenommen, ein neuer Student ("student_id" 10.000) ist gerade an dieser Universität eingetroffen und hat in seiner ersten Klasse eine Reihe von (zufälligen) Noten erhalten. Fügen wir diesen neuen Schüler nun mit Java ein.

              An dieser Universität variiert die "class_id" von 0 bis 500, sodass wir einen beliebigen Wert zwischen 0 und 500 verwenden können.

              • Verbindung zu einer bestimmten Collection herstellen

                • Zunächst müssen wir unsere Create-Klasse einrichten und auf die "sample_training"."grades"-Auflistung zugreifen.
                  package com.mongodb.quickstart;

                  import com.mongodb.client.MongoClient;
                  import com.mongodb.client.MongoClients;
                  import com.mongodb.client.MongoCollection;
                  import com.mongodb.client.MongoDatabase;
                  import org.bson.Document;

                  import java.util.logging.Level;
                  import java.util.logging.Logger;

                  public class Create {

                  public static void main(String[] args) {
                  Logger.getLogger("org.mongodb.driver").setLevel(Level.WARNING);
                  try (MongoClient mongoClient = MongoClients.create(System.getProperty("mongodb.uri"))) {

                  MongoDatabase sampleTrainingDB = mongoClient.getDatabase("sample_training");
                  MongoCollection<Document> gradesCollection = sampleTrainingDB.getCollection("grades");

                  }
                  }
                  }


                  • Ein BSON-Dokument erstellen

                    • Zweitens müssen wir diesen neuen Schüler in Java mithilfe der Document-Klasse darstellen.
                      Random rand = new Random();
                      Document student = new Document("_id", new ObjectId());
                      student.append("student_id", 10000d)
                      .append("class_id", 1d)
                      .append("scores", asList(new Document("type", "exam").append("score", rand.nextDouble() * 100),
                      new Document("type", "quiz").append("score", rand.nextDouble() * 100),
                      new Document("type", "homework").append("score", rand.nextDouble() * 100),
                      new Document("type", "homework").append("score", rand.nextDouble() * 100)));

                      Wie Sie sehen, haben wir aus den vorhandenen Dokumenten in dieser Collection dasselbe Datenmodell reproduziert, da sichergestellt wurde, dass "student_id", "class_id" und "score" alle doppelt vorhanden sind.

                      Außerdem hätte der Java-Treiber das Feld _id mit einer ObjectId für uns generiert, wenn wir hier keine explizite ID erstellt hätten, aber es hat sich bewährt, die _id selbst festzulegen.
                      Dies wird unser Leben im Moment nicht verändern, aber es ist sinnvoller, wenn wir POJOs direkt manipulieren und eine saubere REST-API erstellen möchten.
                      Wie das geht, zeige wir Ihnen in einem künftigen Blogbeitrag.

                      • Insert Operation

                        • Schließlich können wir dieses Dokument einfügen.
                          gradesCollection.insertOne(student);


                          • Endgültiger Code zum Einfügen eines Dokuments

                            • Hier ist die komplette "Create"-Klasse zum Einfügen eines Dokuments in MongoDB mit allen oben genannten Details.
                              package com.mongodb.quickstart;

                              import com.mongodb.client.MongoClient;
                              import com.mongodb.client.MongoClients;
                              import com.mongodb.client.MongoCollection;
                              import com.mongodb.client.MongoDatabase;
                              import org.bson.Document;
                              import org.bson.types.ObjectId;

                              import java.util.Random;
                              import java.util.logging.Level;
                              import java.util.logging.Logger;

                              import static java.util.Arrays.asList;

                              public class Create {

                              public static void main(String[] args) {
                              Logger.getLogger("org.mongodb.driver").setLevel(Level.WARNING);
                              try (MongoClient mongoClient = MongoClients.create(System.getProperty("mongodb.uri"))) {

                              MongoDatabase sampleTrainingDB = mongoClient.getDatabase("sample_training");
                              MongoCollection<Document> gradesCollection = sampleTrainingDB.getCollection("grades");

                              Random rand = new Random();
                              Document student = new Document("_id", new ObjectId());
                              student.append("student_id", 10000d)
                              .append("class_id", 1d)
                              .append("scores", asList(new Document("type", "exam").append("score", rand.nextDouble() * 100),
                              new Document("type", "quiz").append("score", rand.nextDouble() * 100),
                              new Document("type", "homework").append("score", rand.nextDouble() * 100),
                              new Document("type", "homework").append("score", rand.nextDouble() * 100)));

                              gradesCollection.insertOne(student);
                              }
                              }
                              }

                              Sie können diese Klasse mit der folgenden maven-Befehlszeile im Stammverzeichnis oder mit Ihrer IDE ausführen (Einzelheiten finden Sie im vorherigen Beitrag). Vergessen Sie nicht die doppelten Anführungszeichen um die MongoDB-URI, um Überraschungen zu vermeiden.
                              mvn compile exec:java -Dexec.mainClass="com.mongodb.quickstart.Create" -Dmongodb.uri="mongodb+srv://USERNAME:PASSWORD@cluster0-abcde.mongodb.net/test?w=majority"

                              Und hier ist das Dokument, wie es in MongoDB Compass angezeigt wird.
                              {
                              "_id": {
                              "$oid": "5d97c375ded5651ea3462d0f"
                              },
                              "student_id": {
                              "$numberDouble": "10000"
                              },
                              "class_id": {
                              "$numberDouble": "1"
                              },
                              "scores": [{
                              "type": "exam",
                              "score": {
                              "$numberDouble": "4.615256396625178"
                              }
                              }, {
                              "type": "quiz",
                              "score": {
                              "$numberDouble": "73.06173415145801"
                              }
                              }, {
                              "type": "homework",
                              "score": {
                              "$numberDouble": "19.378205578990727"
                              }
                              }, {
                              "type": "homework",
                              "score": {
                              "$numberDouble": "82.3089189278531"
                              }
                              }]
                              }

                              Beachten Sie, dass sich die Reihenfolge der Felder vom ursprünglichen Dokument mit "student_id" unterscheidet: 0.

                              Wir könnten genau die gleiche Reihenfolge erhalten, wenn wir das Dokument wie folgt erstellen möchten.
                              Random rand = new Random();
                              Document student = new Document("_id", new ObjectId());
                              student.append("student_id", 10000d)
                              .append("scores", asList(new Document("type", "exam").append("score", rand.nextDouble() * 100),
                              new Document("type", "quiz").append("score", rand.nextDouble() * 100),
                              new Document("type", "homework").append("score", rand.nextDouble() * 100),
                              new Document("type", "homework").append("score", rand.nextDouble() * 100)))
                              .append("class_id", 1d);

                              Wenn Sie jedoch die Dinge richtig machen, sollte dies keinen Einfluss auf Ihren Code und Ihre Logik haben, da Felder in JSON-Dokumenten nicht sortiert sind.

                              Zitat dazu von json.org.
                              An object is an unordered set of name/value pairs.


                              • Bulk Inserts

                                • Nachdem wir nun wissen, wie ein Dokument erstellt wird, lernen wir, wie viele Dokumente eingefügt werden.

                                  Natürlich können wir die vorherige Einfügeoperation auch einfach in eine for-Schleife einbinden.
                                  In der Tat würden wir, wenn wir diese Methode 10 Mal in einer Schleife ausführen, 10 Einfügebefehle an den Cluster senden und 10 Einfügebestätigungen erwarten.
                                  Wie Sie sich vorstellen können, wäre dies nicht sehr effizient, da dadurch viel mehr TCP-Kommunikation als erforderlich generiert würde.

                                  Stattdessen möchten wir unsere 10 Dokumente verpacken und sie in einem Aufruf an den Cluster senden, und wir möchten nur eine Einfügebestätigung für die gesamte Liste erhalten.

                                  Lass uns den Code überarbeiten. Lassen Sie uns zuerst den Zufallsgenerator zu einem privaten statischen Endfeld machen.
                                  private static final Random rand = new Random();

                                  Erstellen wir eine Factory-Methode für die Noten.
                                  private static Document generateNewGrade(double studentId, double classId) {
                                  List<Document> scores = asList(new Document("type", "exam").append("score", rand.nextDouble() * 100),
                                  new Document("type", "quiz").append("score", rand.nextDouble() * 100),
                                  new Document("type", "homework").append("score", rand.nextDouble() * 100),
                                  new Document("type", "homework").append("score", rand.nextDouble() * 100));
                                  return new Document("_id", new ObjectId()).append("student_id", studentId)
                                  .append("class_id", classId)
                                  .append("scores", scores);
                                  }

                                  Und jetzt können wir damit 10 Dokumente auf einmal einfügen.
                                  List<Document> grades = new ArrayList<>();
                                  for (int classId = 1; classId <= 10; classId++) {
                                  grades.add(generateNewGrade(10001d, classId));
                                  }

                                  gradesCollection.insertMany(grades, new InsertManyOptions().ordered(false));

                                  Wie Sie sehen, verpacken wir jetzt unsere Notendokumente in eine Liste und senden diese Liste in einem einzigen Aufruf mit der "insertMany"-Methode.

                                  Standardmäßig fügt die "insertMany"-Methode die Dokumente der Reihe nach ein und stoppt, wenn während des Vorgangs ein Fehler auftritt.
                                  Wenn Sie beispielsweise versuchen, ein neues Dokument mit derselben "_id" wie ein vorhandenes Dokument einzufügen, erhalten Sie eine "DuplicateKeyException".

                                  Daher würden bei einer geordneten "insertMany" die letzten Dokumente der Liste nicht eingefügt, und der Einfügeprozess würde angehalten und die entsprechende Ausnahme zurückgeben, sobald der Fehler auftritt.

                                  Wie Sie hier sehen können, ist dies nicht das gewünschte Verhalten, da alle Noten völlig unabhängig voneinander sind.
                                  Wenn eine von ihnen ausfällt, möchten wir alle Noten verarbeiten und am Ende Ausnahme Exceptions für die fehlgeschlagenen bekommen.

                                  Aus diesem Grund wird der zweite Parameter "new InsertManyOptions().Ordered(false)" angezeigt, der standardmäßig "true" ist.
                                  • Der vollständige Code

                                    • Lass uns den Code ein wenig schön machen. Hier ist die finale "Create"-Klasse.
                                      package com.mongodb.quickstart;

                                      import com.mongodb.client.MongoClient;
                                      import com.mongodb.client.MongoClients;
                                      import com.mongodb.client.MongoCollection;
                                      import com.mongodb.client.MongoDatabase;
                                      import com.mongodb.client.model.InsertManyOptions;
                                      import org.bson.Document;
                                      import org.bson.types.ObjectId;

                                      import java.util.ArrayList;
                                      import java.util.List;
                                      import java.util.Random;
                                      import java.util.logging.Level;
                                      import java.util.logging.Logger;

                                      import static java.util.Arrays.asList;

                                      public class Create {

                                      private static final Random rand = new Random();

                                      public static void main(String[] args) {
                                      Logger.getLogger("org.mongodb.driver").setLevel(Level.WARNING);
                                      try (MongoClient mongoClient = MongoClients.create(System.getProperty("mongodb.uri"))) {

                                      MongoDatabase sampleTrainingDB = mongoClient.getDatabase("sample_training");
                                      MongoCollection<Document> gradesCollection = sampleTrainingDB.getCollection("grades");

                                      insertOneDocument(gradesCollection);
                                      insertManyDocuments(gradesCollection);
                                      }
                                      }

                                      private static void insertOneDocument(MongoCollection<Document> gradesCollection) {
                                      gradesCollection.insertOne(generateNewGrade(10000d, 1d));
                                      System.out.println("One grade inserted for studentId 10000.");
                                      }

                                      private static void insertManyDocuments(MongoCollection<Document> gradesCollection) {
                                      List<Document> grades = new ArrayList<>();
                                      for (int classId = 1; classId <= 10; classId++) {
                                      grades.add(generateNewGrade(10001d, classId));
                                      }

                                      gradesCollection.insertMany(grades, new InsertManyOptions().ordered(false));
                                      System.out.println("Ten grades inserted for studentId 10001.");
                                      }

                                      private static Document generateNewGrade(double studentId, double classId) {
                                      List<Document> scores = asList(new Document("type", "exam").append("score", rand.nextDouble() * 100),
                                      new Document("type", "quiz").append("score", rand.nextDouble() * 100),
                                      new Document("type", "homework").append("score", rand.nextDouble() * 100),
                                      new Document("type", "homework").append("score", rand.nextDouble() * 100));
                                      return new Document("_id", new ObjectId()).append("student_id", studentId)
                                      .append("class_id", classId)
                                      .append("scores", scores);
                                      }
                                      }

                                      Zur Erinnerung, jeder Schreibvorgang (create, replace, update, delete), der an einem EINZELNEN Dokument ausgeführt wird, ist in MongoDB ACID.
                                      Was bedeutet, dass insertMany standardmäßig nicht ACID ist, aber gute Nachrichten, seit MongoDB 4.0 können wir diesen Aufruf in eine ACID-Transaktion mit mehreren Dokumenten einbinden, um ihn vollständig ACID zu machen.

                                      • Zusammenfassung

                                        • Wir haben uns angesehen, wie Sie MongoDB BSON-Dokumente in Java erstellen und einzeln mit der "insertOne"-Methode oder mit der "insertMany"-Methode für Masseneinfügungen in MongoDB einfügen.

                                          Der MongoDB Java Treiber unterstützt auch eine direkte Zuordnung zwischen POJOs und BSON-Dokumenten mithilfe von Codecs.
                                          Auch das ist ein Thema für einen künftigen Blog-Beitrag.
                                          Die Verwendung der Document-Klasse wie in diesem Blog-Beitrag ist jedoch die beste Möglichkeit, mit Daten zu arbeiten, die keinem strengen Datenmodell folgen.
                                          Sie können Codecs und POJOs nur dann nutzen, wenn Sie über ein festes Datenmodell verfügen.

Latest member activities

Tags

Recommend this community post