springmongodbspring-mvcspring-bootmongodb-query

Find/Remove in @DBref list items in MongoDB for Spring


What would be the best approach to find and update nested list items as @DBRef in MongoDB for Spring?

I have a AppliedApplication class:

@Document(collection = "applied_application")
public class AppliedApplication {

    @Id
    private String id;
    @Field("program")
    @DBRef
    private List<Program> programList;

    // getters and setters

}

With a Program class as @DBRef:

@Document(collection = "program")
    public class Program {

        @Id
        private String id;
        @Field("program_name")
        private String programName;

        // getters and setters

    }

I'm looking for a way to find and update the nested list items using the following queries:

Query used for finding a Program object by It's Id from AppliedApplication collection:

Query query = new Query();
     query.addCriteria(Criteria.where("id").is(applicationId)
      .and("program.$id").is(new ObjectId(programId)));

Program program = mongoTemplate.findOne(query, Program.class);

Query used for removing list item from AppliedApplication:

Update update = new Update().pull("program", new BasicDBObject("program.$id", new ObjectId(programId)));

mongoTemplate.updateMulti(new Query(), update, AppliedApplication.class);

None of them are working and I'm completely clueless.


Solution

  • Find:

    Use positional operator/$elemMatch for finding the matching Program DBRef in the AppliedApplication.

    Using $positional projection

    Query query = new Query();
    query.addCriteria(Criteria.where("id").is(new ObjectId(applicationId)).and("program.$id").is(new ObjectId(programId)));
    query.fields().position("program", 1);
    AppliedApplication application = mongoTemplate.findOne(query, AppliedApplication.class);
    Program program = application.getProgramList().get(0);
    

    Using $elemMatch projection

    Query query = new Query();
    query.addCriteria(Criteria.where("id").is(new ObjectId(applicationId)));
    query.fields().elemMatch("program", Criteria.where("$id").is(new ObjectId(programId)));
    AppliedApplication application = mongoTemplate.findOne(query, AppliedApplication.class);
    Program program = application.getProgramList().get(0);
    

    Remove:

    Use $pull to remove the DBRef from list of program DBref's.

    Query query = Query.query(Criteria.where("$id").is(new ObjectId(programId)));
    Update update = new Update().pull("program", query);
    mongoTemplate.updateMulti(new Query(), update, AppliedApplication.class);
    

    Add

    Use $push to add new programs to the list.

    Query query = new Query();
    query.addCriteria(Criteria.where("id").is(new ObjectId(applicationId)));
    Update update = new Update().push("program", new DBRef("program", new ObjectId(programId));
    mongoTemplate.updateMulti(query, update, AppliedApplication.class);