Retrieve all the documents matching the criteria in an array elements which is a subdocument

 {
    "_id" : ObjectId("577b54816081dd32cd3e2d60"),
    "user" : ObjectId("577b54816081dd32cd3e2d5e"),
    "journals" : [ 
        {
            "title" : "Journal Title2",
            "desc" : "desx2",
            "feeling" : 3,
            "date" : ISODate("2016-07-05T06:32:45.404Z"),
            "deleteFl" : true,
            "_id" : ObjectId("577b548d6081dd32cd3e2d64")
        }, 
        {
            "title" : "Journal Title3",
            "desc" : "desx3",
            "feeling" : 3,
            "date" : ISODate("2016-07-05T06:49:00.156Z"),
            "deleteFl" : false,
            "_id" : ObjectId("577b585c6081dd32cd3e2d6d")
        }, 
        {
            "title" : "Journal Title4",
            "desc" : "desx4",
            "feeling" : 3,
            "date" : ISODate("2016-07-05T06:49:06.700Z"),
            "deleteFl" : false,
            "_id" : ObjectId("577b58626081dd32cd3e2d70")
        }
    ]
}

Above is my document structure

now, I need all the journal documents whose deleteFl = false.

I tried in this way using Java Mongo driver

getDatabase().getCollection("journals").find(and(eq("user", user), eq("journals.deleteFl", false)));

but still it gives me back all the documents including “deleteFl”: true. any help here ?

Answer

Actually, your query returns 1 document, because the data is inside 1 document. What you want is to limit the returning fields of a document (limit subdocuments).

Note: You can do that using elemMatch in the projection, to limit the fields returned by the query. But elemMatch will return just one subdocument. (I posted a deleted wrong answer using elemMatch)

When you want all subdocuments and only specific subdocuments from inside an array, you need to use the aggregation pipeline. Here is a tested code that does what you want (just change DB and colelction name):

    MongoClient mongoClient = new MongoClient();
    MongoDatabase db = mongoClient.getDatabase("test");
    MongoCollection collection = db.getCollection("test");

    Iterable<Document> output = collection.aggregate(asList(
             new BasicDBObject("$unwind", "$journals"),
             new BasicDBObject("$match", new BasicDBObject("journals.deleteFl", false))
    ));

    for (Document dbObject : output)
    {
        System.out.println(dbObject);
    }

Leave a Reply

Your email address will not be published. Required fields are marked *