0

1)关于问题的语境化:

我正在尝试使用 03 个不同的服务/存储库(userService + postService + userRepo)在 03 个不同的 DB-Collections(Reactive MongoDB)中“删除”项目;

我的目标是使用相同的链接代码同时删除一个对象(在每个集合中);

以下是上述情况的代码:

1.1) 代码:

当前工作状态:不工作;

当前行为:不执行任何删除,无论是 delete-userService、delete-postService 还是 delete-userRepo。

@Slf4j
@Service
@AllArgsConstructor
public class UserService implements UserServiceInt {

  private final UserRepo userRepo;

  private final PostServiceInt postServ;

  private final CommentServiceInt comServ;

  private final CustomExceptions customExceptions;

  @Override
  public Mono<Void> deleteInThreeCollections(String id) {
    return userRepo
           .findById(id)
           .switchIfEmpty(customExceptions.userNotFoundException())
           
           .map(user -> {
             userRepo.delete(user); // First deletion - delete-method from userRepo
             return user;
           })

           .flatMapMany(user -> postServ.findPostsByAuthorId(user.getId()))
           .map(post -> {
             postServ.delete(post); // Second deletion - delete-method from postService
             return post;
           })

           .flatMap(post -> comServ.findCommentsByPostId(post.getPostId()))
           .map(comServ::delete) // Third deletion - delete-method from commentService
           .then()
           ;
  }
}

2)问题:

  • 如何删除不同 DB-Collections 中的不同元素,
    • 通过仅使用一个使用三个“删除方法”的“链式删除方法”
      • 三种不同的服务/repo(userService + postService + userRepo?

3)更新:

找到解决方案

@Override
 public Mono<Void> deleteInThreeCollections(String id) {
  return userRepo
         .findById(id)
         .switchIfEmpty(customExceptions.userNotFoundException())
         .flatMap(
                user -> postServ
                       .findPostsByAuthorId(user.getId())
                       .flatMap(
                              post -> comServ.findCommentsByPostId(
                                     post.getPostId())
                                             .flatMap(comServ::delete)
                                             .thenMany(
                                                    postServ.findPostsByAuthorId(
                                                           post.getAuthor()
                                                               .getId()))
                                             .flatMap(postServ::delete)
                               )
                       .then(userRepo.delete(user))
                 );
 }

非常感谢您的帮助

4

1 回答 1

1

假设您的someclass.delete()操作返回Mono<Something>.

主要问题是map不会订阅内部发布者。

这里你必须使用flatMap/ concatMap... 操作,它们会订阅内部发布者(例如 xyz.delete)

如果您的删除方法没有返回删除的项目,您可以使用then(object)给定参数返回。

如我所见,您不能同时而是按顺序执行所有删除操作,因为每个操作输入参数都是前一个操作的输出。如果您考虑批量处理所有帖子或评论......同时删除,这是可能的。您可以collectListid-s 并创建批处理操作 ( deleteByIdIn(list of ids)) 或创建并行通量并同时运行删除操作(批处理更好)。

在这里,我创建了一个带有假服务的最小示例来演示它:

import org.junit.jupiter.api.Test
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.test.StepVerifier

data class User(
    val id: String
)

data class Post(
    val id: String
)

data class Comment(
    val id: String
)

class UserRepo {

    fun finById(id: String): Mono<User> {
        println("Find an user")
        return Mono.just(User("1"))
    }

    //example if delete gives back the object
    fun delete(user: User): Mono<User> {
        println("delete $user")
        return Mono.just(user)
    }

}

class PostServiceInt {

    fun findPostsByAuthorId(userId: String): Flux<Post> = Flux.fromIterable(listOf(Post("1"), Post("2")))

    //and if not
    fun delete(post: Post): Mono<Void> {
        println("delete $post")
        return Mono.empty()
    }

}


class CommentServiceInt {

    fun findCommentsByPostId(postId: String): Flux<Comment> = Flux.fromIterable(listOf(Comment("10"), Comment("7"),Comment("3"),Comment("4")))

    fun delete(comment: Comment): Mono<Comment> {
        println("delete $comment")
        return Mono.just(comment)
    }

}


class Example {

    val userRepo = UserRepo()
    val postServ = PostServiceInt()
    val comServ = CommentServiceInt()

    @Test
    fun test() {
        val result = userRepo.finById("1")
            .switchIfEmpty(Mono.error { RuntimeException() })
            .flatMap { user -> userRepo.delete(user) }
            .flatMapMany { user -> postServ.findPostsByAuthorId(user.id) }
            .flatMap { post -> postServ.delete(post).then(Mono.just(post)) }
            .flatMap { post -> comServ.findCommentsByPostId(post.id) }
            .flatMap { comment -> comServ.delete(comment) }

        StepVerifier.create(result)
            .expectNextCount(4)
            .verifyComplete()


    }
    
}
于 2021-06-10T21:40:19.157 回答