Search code examples
javamongodbmongo-java-drivernested-documents

How to read attributes out of multiple nested documents in MongoDB Java?


I need some help with a project I am planing to do. At this stage I am trying to learn using NoSQL Databases in Java. I've got a few nested documents looking like this: MongoDB nesting structure

enter image description here

Like you can see on the image, my inner attributes are "model" and "construction".

Now I need to iterate through all the documents in my collection, whose keynames are unknown, because they are generated in runtime, when a user enters some information.

At the end I need to list them in a TreeView, keeping the structure they have already in the database. What I've tried is getting keySets from documents, but I cannot pass the second layer of the structure. I am able to print the whole Object in Json format, but I cannot access the specific attributes like "model" or "construction".

MongoCollection collection= mongoDatabase.getCollection("test");           
MongoCursor<Document> cursor = collection.find().iterator();
for(String keys: document.keySet()) {
                Document vehicles = (Document) document.getString(keys);

                //System.out.println(keys);
                //System.out.println(document.get(keys));
            }

                /Document cars = (Document) vehicle.get("cars");
                Document  types = (Document) cars.get("coupes");
                Document brands = (Document) types.get("Ford");
                Document model = (Document) brands.get("Mustang GT");

Here I tried to get some properties, by hardcoding the keynames of the documents, but I can't seem to get any value either. It keeps telling me that it could not read from vehicle, because it is null.

The most tutorials and posts in forums, somehow does not work for me. I don't know if they have any other version of MongoDB Driver. Mine is: mongodb driver 3.12.7. if this helps you in any way.

I am trying to get this working for days now and it is driving me crazy. I hope there is anyone out there who is able to help me with this problem.


Solution

  • Here is a way you can try using the Document class's methods. You use the Document#getEmbedded method to navigate the embedded (or sub-document) document's path.

    try (MongoCursor<Document> cursor = collection.find().iterator()) {
        while (cursor.hasNext()) {
        
            // Get a document
            Document doc = (Document) cursor.next();
            
            // Get the sub-document with the known key path "vehicles.cars.coupes"
            Document coupes = doc.getEmbedded(
                                        Arrays.asList("vehicles", "cars", "coupes"), 
                                        Document.class);
            
            // For each of the sub-documents within the "coupes" get the
            // dynamic keys and their values.
            for (Map.Entry<String, Object> coupe :  coupes.entrySet()) {
            
                System.out.println(coupe.getKey()); // e.g., Mercedes
                
                // The dynamic sub-document for the dynamic key (e.g., Mercedes):
                // {"S-Class": {"model": "S-Class", "construction": "2011"}}
                Document coupeSubDoc = (Document) coupe.getValue(); 
                
                // Get the coupeSubDoc's keys and values
                coupeSubDoc.keySet().forEach(k -> {
                    System.out.println("\t" + k); // e.g., S-Class
                    System.out.println("\t\t" + "model" + " : " +
                        coupeSubDoc.getEmbedded(Arrays.asList(k, "model"), String.class));
                    System.out.println("\t\t" + "construction" + " : " +
                        coupeSubDoc.getEmbedded(Arrays.asList(k, "construction"), String.class));
                });
            }
        }
    }
    

    The above code prints to the console as:

    Mercedes
            S-Class
                    model : S-Class
                    construction : 2011
    Ford
            Mustang
                    model : Mustang GT
                    construction : 2015