1

I have a MongoDB document structure like this:

{ 
  "name": "list"
  "config": "default"
  "items": [
    {
      "email": "[email protected]"
      "status": true
      "number": 123
    },
    ...
    {
      "email": "[email protected]"
      "status": false
      "number": 432
    },
   ]
}

Now, how can I retrive multiple subdocuments that much certain criteria. For instance, I want to obtain all documents where status = true. I know that it is possible to use $elemMatch, but it returns only the first matching instance and I need ALL documents that correspond to the specified condition. Please show how can it be done with Java.

3
  • 1
    $elemMatch does not return only the first mathing instance. It returns all the documents that matched with the given criteria. Check docs again. docs.mongodb.org/manual/reference/operator/elemMatch Commented Sep 11, 2013 at 9:12
  • Yes, indeed I saw that doc, but in Java I cannot figure out how to do it. Also there is this kind of $elemMatch docs.mongodb.org/manual/reference/projection/elemMatch. I am a little confused how to use it so that I could retrive multiple values. Commented Sep 11, 2013 at 9:17
  • parvin, could you please show the example in Java of how to use $elemMatch to obtain multiple fields. Thanks in advance! Commented Sep 11, 2013 at 9:27

2 Answers 2

2

You can do it in Java as follows.

        Mongo mongo = new Mongo("localhost:27017");
        DB db = mongo.getDB("myDB");
        DBCollection coll = db.getCollection("myCollection");

        DBObject statusQuery = new BasicDBObject("status", true);
        DBObject elemMatchQuery = new BasicDBObject("$elemMatch", statusQuery);

        DBObject fields = new BasicDBObject();
        fields.put("items", elemMatchQuery);
        fields.put("name", 1);
        fields.put("config", 1);

        DBCursor cur = coll.find(new BasicDBObject(), fields);

        while (cur.hasNext()) {
            DBObject obj = cur.next();
            // Get fields from object
        }
Sign up to request clarification or add additional context in comments.

3 Comments

parvin, thanks for your answer. Actually, I used the similar idea to do this. However, the problem is still present I launched your code and got the same issue. Now in my "items" array I have only two docs, one with false status and one with true, when I run the code I got both results! But I only need the one with true. Where can be the problem?
You want to project your results. I have updated the code above. Check it again.
Why is filtering data (i.e. elemMatchQuery) joined with projection data and the filtering data (i.e. fields), while the filtering parameter is a blank object (i.e. new BasicDBObject() in coll.find) !?
0

If you want all subdocuments from the list items in separate documents, you can $unwind the list. I also added filter matching status is true:

try (MongoClient client = new MongoClient()) {

        MongoDatabase db = client.getDatabase("myDB");
        MongoCollection<BsonDocument> collection = db.getCollection("myColl", BsonDocument.class);

        MongoCursor<BsonDocument> cursor =
                collection.aggregate(Arrays.asList(new Document("$unwind", "$items"),
                                                    new Document("$match", new Document("items.status", true)))).iterator();

        try {
            while (cursor.hasNext()) {
                // I think this is what you need
                BsonDocument bsonDocument = cursor.next().getDocument("items");

                // and if you just want emails
                String email = bsonDocument.get("email").asString().getValue();
                System.out.println(email);
            }

        } finally {
            cursor.close();
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.