Spring Data - MongoRepository - @Query to find item within nested list of objects

1k Views Asked by At

I'm trying to query MongoDB to return a single Answer object contained within a QuestionDocument object.

I am using Spring, MongoRepository, and JDK 11.

My QuestionDocument POJO:

@Data
@Document(collection = "Questions")
@AllArgsConstructor(onConstructor = @__(@Autowired))
@NoArgsConstructor
     public class QuestionDocument {
     @Id
     private String questionId;
     (...) 
     private List<Answer> answers;
     (...)
}

My Answer POJO:

@Data
public class Answer implements Serializable {
     private String answerId;
     (...)

My QuestionRepository:

@Repository
public interface QuestionRepository extends MongoRepository<QuestionDocument, String> {
     @Query(value = "{ { 'questionId' : ?0 }, { 'answers.$answerId' : ?1 } }")
     Answer findByQuestionIdAndAnswerId(String questionId, String answerId);

My QuestionServiceImpl:

public getAnswer(String questionId, String answerId){
     Answer answer = findByQuestionIdAndAnswerId(questionId, answerId);
     return answer;
}

protected Answer findByQuestionIdAndAnswerId(String questionId, String answerId){
     Answer answer;
     try {
     answer = questionRepository.findByQuestionIdAndAnswerId(questionId, answerId);
     } catch (Exception e) {
     throw new IllegalArgumentException("There is no answer with this ID.");
}
     return answer;
}

When I hit my endpoint in Postman, the correct response body appears, but all of its values are null. I have verified that the correct questionId and answerId are passed in my parameters.

I have also consulted several additional SO posts and Spring and MongoDB documentation, but so far, implementing what I've read regarding traversing nested objects by property hasn't helped.

How does my @Query value need to change to properly return a specific Answer object from this nested list of answers?

I have attempted to create findBy methods like: findByQuestion_Answers_AnswerId(String answerId);

I have attempted to add @DBRef above my List<Answer> answers, and adding @Document(collection = "Answers") and @Id above private String answerId; in my Answer POJO. I then cleared my database, created a new question and answer, and queried for the specific answerId, and still returned null data.

What I expect, is that given the questionId and answerId, the query will return one Answer object and its associated information (answerBody, answerAuthor, etc.).

My postman response states SUCCESS, but the data is null.

1

There are 1 best solutions below

2
Noel On

You can change the Query to this.

@Query(value = "{{'questionId' : ?0, 'answers.answerId' : ?1}}")

or, just define this method.

findByQuestionIdAndAnswerId(String questionId, String answerId);

The return type will be of QuestionDocument, not Answer.

More details here.