0

Let's say I've these 2 documents:

 @Document
 public class Exam {
   private int examId;
   private List<Question> questions;

and

 public class Question {
   private int questionId;
   private String question;

I need to write a 'findAll' that returns a List of ALL Questions (or ideally only 'question' string in the Question object) for a certain 'Exam' object (examId == n) using MongoRepository or some other way in Java using Spring Data MongoDb, how do I do that?

{
    "_id" : ObjectId("xyz"),
    "_class" : "com.xxx.Exam",
    "examId" : 1,
    "questions" : [ 
        {"questionId" : 1, "question" : "xyz" },
        {"questionId" : 2, "question" : "abc" }
    ]
}
BiJ
  • 1,639
  • 5
  • 24
  • 55
DilTeam
  • 2,551
  • 9
  • 42
  • 69
  • can you provide collections structure – Jain Aug 12 '16 at 19:04
  • Your modeling is questionable. With MongoDB, you usually don't use a join; instead, you embed your `Question`s into the `Exam`. Then just retrieve the exam. – chrylis -cautiouslyoptimistic- Aug 12 '16 at 19:16
  • Sorry. Question is NOT another Document. Just an embedded object. – DilTeam Aug 12 '16 at 19:48
  • Possible duplicate of [spring data - Mongodb - findBy Method for nested objects](http://stackoverflow.com/questions/12730370/spring-data-mongodb-findby-method-for-nested-objects) – helmy Aug 12 '16 at 20:34
  • No. This is not a duplicate of that. I had already read that one. Here I need to get ALL the nested objects. In that one, the author is updating a particular 'question'. – DilTeam Aug 12 '16 at 20:45

1 Answers1

0

There more than one way to do that, one of them could be like this:

MatchOperation match = match(new Criteria("examId").is(1));
UnwindOperation unwind = unwind("questions");
ProjectionOperation project = project().andExclude("_id").and("questions.question").as("question");
Aggregation aggregation = newAggregation(match, unwind, project);
AggregationResults<DBObject> result = mongoOperations.aggregate(aggregation, "exams", DBObject.class);

result.forEach(new Consumer<DBObject>() {
    @Override
    public void accept(DBObject t) {
        System.out.println(t.toString());
    }
});
// otuput
// { "question" : "xyz"}
// { "question" : "abc"}

The result is mapped to DBObject here, however you can define more appropriate class.

Andriy Simonov
  • 1,276
  • 1
  • 11
  • 19
  • Where's project() coming from? – DilTeam Aug 13 '16 at 00:29
  • [project()](https://docs.mongodb.com/manual/reference/operator/aggregation/project/) is a stage in the aggregation pipeline, it is in the query to flatten the nested "questions.question" documents. – Andriy Simonov Aug 13 '16 at 05:17