Nirbhay Mishra
Nirbhay Mishra

Reputation: 1648

How can I find selected array elements from mongo

I want to find only select array elements from a mongo document.like in following document I want to return only hard questions from array. am using mongo driver for java.

BasicDBObject query=new BasicDBObject("questionList.type", "hard");
DBCursor curssc  = collection.find(query);

Document

{
   "testpaperid": 1,
   "testpaperNo": "science",
   "questionList":
      [
         {
            "question": "this is question no 1",
            "type": "hard"
         },
         {
            "question": "this is question no 2",
            "type":"simple"
         },
         {
            "question": "this is question no 3",
            "type": "hard"
         }
      ] 
}

Upvotes: 1

Views: 1260

Answers (2)

Neo-coder
Neo-coder

Reputation: 7840

If using $elemMatch operator it limits the contents of an <array> field from the query results to contain only the first element matching the $elemMatch condition.

So If you run this query :

db.collectionName.find({"questionList":{"$elemMatch":{"type":"hard"}}},{"questionList.type.$":1})

and above query equivalent code in java as below :

BasicDBObject eleMatch = new BasicDBObject();
eleMatch.put("type", "hard");
BasicDBObject elemMatchQuery = new BasicDBObject();
elemMatchQuery.put("$elemMatch", eleMatch);
BasicDBObject query = new BasicDBObject();
query.put("questionList", elemMatchQuery);
BasicDBObject projection = new BasicDBObject();
projection.put("questionList.type.$", 1);
DBCollection dbcoll = mongoTemplate.getCollection("collectionName");
DBObject object = dbcoll.find(query, projection);

This return only first matching type:hard output contains "questionList" : [ { "question" : "this is question no 1", "type" : "hard" } ] not all questionList array which contains type:hard

For avoiding this should use mongo java aggregation driver and mongo aggregation query looks like :

db.collectionName.aggregate({
  "$unwind": "$questionList"
}, {
  "$match": {
    "questionList.type": "hard"
  }
}, {
  "$group": {
    "_id": "$_id",
    "testpaperid": {
      "$first": "$testpaperid"
    },
    "testpaperNo": {
      "$first": "$testpaperNo"
    },
    "questionList": {
      "$push": "$questionList"
    }
  }
}).pretty()

and this aggregation query in java as below :

// unwind  questionList
DBObject unwind = new BasicDBObject("$unwind", "$questionList");
// create  pipeline operations, with the $match
DBObject match = new BasicDBObject("$match", new BasicDBObject("questionList.type", "hard"));
// Now the $group operation  
DBObject groupFields = new BasicDBObject("_id", "$group field");
groupFields.put("testpaperid", new BasicDBObject("$first", "$testpaperid"));
groupFields.put("testpaperNo", new BasicDBObject("$first", "$testpaperNo"));
groupFields.put("questionList", new BasicDBObject("$push", "$questionList"));
DBObject group = new BasicDBObject("$group", groupFields);
// run aggregation
List < DBObject > pipeline = Arrays.asList(unwind, match, group);
AggregationOutput output = collectionName.aggregate(pipeline);
for(DBObject result: output.results()) {
  System.out.println(result);
}

Upvotes: 3

bagrat
bagrat

Reputation: 7418

When you use array operators in a regular query in MongoDB, it returns the documents that match the query criteria, and return the whole document, including the contents of the array field. This means that you cannot filter out some documents from an array field using a regular query.

But you can do that using the aggregation query. The following query is an aggregation query for mongo-shell, which you can easily translate to Java driver code:

db.quest.aggregate(
   [
      {$unwind: '$questionList'}, 
      {$match: {'questionList.type': 'hard'}}, 
      {$group: 
         {
            _id: {
                    _id: '$_id', 
                    testpaperid: '$testpaperid', 
                    testpaperNo: '$testpaperNo'
                 }, 
            questionList: {$push: '$questionList'}
          }
       }, 
       {$project: {
                     _id: '$_id._id', 
                     testpaperid: '$_id.testpaperid', 
                     testpaperNo: '$_id.testpaperNo', 
                     questionList: 1
                  }
       }
   ]
)

Upvotes: 0

Related Questions