Get value from Embedded Document Mongo Java Get value from Embedded Document Mongo Java mongodb mongodb

Get value from Embedded Document Mongo Java


You can do it one of three ways.

You can use aggregation framework to project the value of embedded field using dot notation.

Using Aggregation

 import static com.mongodb.client.model.Aggregates.*; import static com.mongodb.client.model.Filters.eq; import static com.mongodb.client.model.Projections.computed; import static java.util.Arrays.*; import static com.mongodb.client.model.Projections.include; MongoClient mc = new MongoClient(); MongoDatabase db = mc.getDatabase("test"); MongoCollection<Document> collection = db.getCollection("collection"); Document document =      collection.aggregate(asList(        match(eq("day",17)),        project(computed("val", "$model1.MondayModel.gtxdotdot.xdotdot")))).     first(); Double embeddedField = document.getDouble("val");

Using Distinct

 Double embeddedField = collection.distinct("model1.MondayModel.gtxdotdot.xdotdot", eq("day",17), Double.class).first();

Using Find

 Document document = collection.find(eq("day",17)).projection(include("model1.MondayModel.gtxdotdot.xdotdot")).first(); Double embeddedField = document.get("model1", Document.class).get("MondayModel", Document.class).get("gtxdotdot", Document.class).getDouble("xdotdot")


I don't think you can use dot notation directly, but you can create your own helper function.

Solution 1: get field with dot notation

public static Object getWithDotNotation( Document document, String dots )      throws MongoException{    String[] keys = dots.split( "\\." );    Document doc = document;    for( int i = 0; i < keys.length - 1; i++ ){        Object o = doc.get( keys[ i ] );        if( o == null || !( o instanceof Document ) ){            throw new MongoException( String.format(                     "Field '%s' does not exist or s not a Document", keys[ i ] ) );        }        doc = ( Document ) o;    }//end for    return doc.get( keys[ keys.length - 1 ] );}

You can then use it like this:

String dotNotation = "model1.MondayModel.gtxdotdot.xdotdot";FindIterable<Document> projection = mongoColl.find()    .projection( fields( include( dotNotation ) ) );Double value = ( Double ) getWithDotNotation( projection.first(), dotNotation );System.out.println( value ); // result: 0.0

This will simplify your code a whole lot. The only things to care for are:

  • if you are not sure of you dot notation, use a try catch block
  • the method getWithDotNotation might return null
  • be careful about forced casts, use it only if you are 100% sure of the type of your data (here Double).

Solution 2: flatten your doc

public static Document flattenDoc( Document document ){    Document flattened = new Document();    Queue<Pair<String, Document>> queue = new ArrayDeque<>();    queue.add( new Pair<>( "", document ) );    while( !queue.isEmpty() ){        Pair<String, Document> pair = queue.poll();        String key = pair.getKey();        for( Map.Entry<String, Object> entry : pair.getValue().entrySet() ){            if( entry.getValue() instanceof Document ){                queue.add( new Pair<>( key + entry.getKey() + ".", ( Document ) entry.getValue() ) );            }else{                flattened.put( key + entry.getKey(), entry.getValue() );            }        }//end for    }    return flattened;}

With your sample data, the result of flattenDoc is the following:

Document{{_id=569afce4b932c542500143ec,date=2016-1-17T2:31:0Z,day=17,model1.date=2016-01-17T02:31+0000,model1.MondayModel.gtxdotdot.xdotdot=0.0,model1.MondayModel.gtxdotdot.xdot=0.0,model1.MondayModel.lsxdotdot.xdotdot=0.0,model1.MondayModel.lsxdotdot.xdot=0.0,model1.MondayModel.gtxdot.xdotdot=0.0,model1.MondayModel.gtxdot.xdot=0.0,model1.MondayModel.lsxdot.xdotdot=0.0,model1.MondayModel.lsxdot.xdot=0.0,model1.MondayModel.modeldotdot.mean=0.0,model1.MondayModel.modeldotdot.sdvar=0.0,model1.MondayModel.modeldot.mean=0.0,model1.MondayModel.modeldot.sdvar=0.0}}

So you can use getDouble("model1.MondayModel.gtxdotdot.xdotdot") directly. This approach might be more efficient if you need to access all the fields.