Как использовать ссылки на БД с реактивными Spring Data MongoDB? - PullRequest
0 голосов
/ 27 апреля 2018

Я новичок в MongoDB и Reactor и пытаюсь получить пользователя с его профилями Вот это POJO:

public class User {

    private @Id String id;
    private String login;
    private String hashPassword;
    @Field("profiles") private List<String> profileObjectIds;
    @Transient private List<Profile> profiles; }

public class Profile {

    private @Id String id;
    private @Indexed(unique = true) String name;
    private List<String> roles; }

Проблема в том, как добавить профили в пользовательский POJO?

Я знаю, что могу поставить @DBRef и решить проблему, но в документации документации MongoDB указать руководство Ref должно быть предпочтительнее, чем DB ref.

Я вижу два решения:

  1. Заполните Pojo, когда я получу его:

    public Mono<User> getUser(String login) {
        return userRepository.findByLogin(login)
        .flatMap(user -> ??? );
    }
    

Я должен что-то сделать с profileRepository.findAllById () , но я не знаю или не согласен с обоими издателями, учитывая, что результаты профилей зависят от результатов пользователя.

  1. Объявите AbstractMongoEventListener и переопределите метод onAfterConvert:

Но здесь я ошибаюсь, так как метод завершается до публикации результата

public void onAfterConvert(AfterConvertEvent<User> event) {
    final User source = event.getSource();
    source.setProfiles(new ArrayList<>());
    profileRepository.findAllById(source.getProfileObjectIds())
    .doOnNext(e -> source.getProfiles().add(e))
    subscribe();
}

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

TL; DR

В реактивной Spring Data MongoDB нет поддержки DBRef, и я не уверен, что она будет.

Объяснение

Проекты Spring Data организованы в компоненты Template API, Converter и Mapping Metadata. Императивная (блокирующая) реализация Template API использует императивный подход для извлечения Document s и преобразования их в объекты домена. В частности, MappingMongoConverter обрабатывает все преобразования и DBRef разрешение. Этот API работает в синхронном / императивном API и используется как для реализации API-шаблона (императивной, так и для реактивной).

Повторное использование MappingMongoConverter было логичным решением при добавлении реактивной поддержки, поскольку нам не нужно дублировать код. Единственное ограничение - разрешение DBRef, которое не соответствует модели реактивного выполнения.

Для поддержки реактивных DBRef с преобразователь должен быть разделен на несколько бит, а вся обработка ассоциации требует капитального ремонта.

Ссылка: https://jira.spring.io/browse/DATAMONGO-2146

Рекомендация

Сохраните ссылки в качестве ключей / идентификаторов в модели вашего домена и ищите их по мере необходимости. zipWith и flatMap - соответствующие операторы, в зависимости от того, что вы хотите заархивировать (улучшить модель с помощью ссылок, только ссылки поиска).

На заметку по теме: Reactive Spring Data MongoDB поставляется частично с сокращенным набором функций. Контекстное расширение SpEL - это функция, которая не поддерживается, поскольку эти компоненты предполагают императивную модель программирования и, следовательно, синхронное выполнение.

0 голосов
/ 27 апреля 2018

Во-первых, я наконец-то добился того, что хотел:

public Mono<User> getUser(String login) {
   return userRepository.findByLogin(login)
         .flatMap( user ->
              Mono.just(user)
              .zipWith(profileRepository.findAllById(user.getProfileObjectIds())
                  .collectionList(),
                  (u, p) -> {
                       u.setProfiles(p);
                       return u;
                   })
            );
}
...