spring-data-mongodb @Update annotation with arrayFilters

Viewed 348

spring-data-mongodb 3.4.0 have a beautiful @Update annotation support for jpa repositories.

But how can i pass arrayFilters and other options, supported by https://www.mongodb.com/docs/manual/reference/method/db.collection.update/ ?

Here is my working manual example:

public @NotNull Comment addComment(String id, String cid, String lid, String sid, Comment comment) {
        // Add comment
        JwtUser user = userService.getCurrentUser().orElseThrow(() ->
                new SodixException("Can't get current user"));

        EditorUser author = EditorUser.builder()
                .id(user.getExternalId())
                .username(user.getUsername())
                .firstName(user.getFirstName())
                .lastName(user.getLastName())
                .build();

        CommentEntity commentToSave = new CommentEntity();
        commentToSave.setId(ProjectIdUtil.generateCommentId());
        commentToSave.setCreatedAt(LocalDateTime.now());
        commentToSave.setAuthor(author);
        commentToSave.setMessage(comment.getMessage());

        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        query.addCriteria(Criteria.where("chapters").elemMatch(
                Criteria.where("_id").is(cid).and("lessons").elemMatch(
                        Criteria.where("_id").is(lid).and("sections").elemMatch(
                                Criteria.where("_id").is(sid)
                        )
                )
        ));

        Update update = new Update();
        update.addToSet("chapters.$[c].lessons.$[l].sections.$[s].comments", commentToSave);
        update.filterArray("c._id", cid);
        update.filterArray("l._id", lid);
        update.filterArray("s._id", sid);

        var result = mongoTemplate.updateFirst(query, update, ProjectEntity.class);
        if (result.getModifiedCount() < 1) {
            throw new RuntimeException("Comment wasn't added");
        }
}

Here is what i expect to run using repository @Update annotation, but it's not working yet:

import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.mongodb.repository.Update;
...
@Repository
public interface ProjectRepository extends MongoRepository<ProjectEntity, String> {
...
    @Query("{ _id : ?0, chapters : {$elemMatch : {_id: ?1, lessons: {$elemMatch: {_id: ?2, 'sections._id': ?3}}}}}")
    @Update("{$set : { 'chapters.$[c].lessons.$[l].sections.$[s].comments' : ?4 }, $arrayFilters: {'c._id': ?1, 'l._id': ?2, 's._id': ?3}}")
    long addComment(String id, String cid, String lid, String sid, CommentEntity comment);
    
    ...
}

Error i've got is:

com.mongodb.MongoWriteException: Write operation error on server localhost:27017. Write error: WriteError{code=2, message='No array filter found for identifier 'c' in path 'chapters.$[c].lessons.$[l].sections.$[s].comments'', details={}}.

Thanks for the help!

0 Answers
Related