我是MongoDB和反应堆的新手,我正在尝试通过与用户相关的配置文件来检索用户这是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。
我看到了两个解决方案:
当我得到它时,请填充POJO:
public Mono<User> getUser(String login) { return userRepository.findByLogin(login) .flatMap(user -> ??? ); }
我应该用 prifilerepository.findallbyid((做点事
- 声明AbstrackMongoEventListener和Override onFterConvert方法:
,但是在这里我误会了,因为该方法在结果发布之前结束
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();
}
tl; dr
反应性弹簧数据中没有DBRef
支持,我不确定会有。
说明
春季数据项目被组织为模板API,转换器和映射元数据组件。模板API的命令性(阻止(实现使用命令式方法来获取Document
S并将其转换为域对象。MappingMongoConverter
特别处理所有转换和DBRef
分辨率。该API在同步/命令性API中起作用,用于模板API实现(势在必行和反应性(。
重复使用MappingMongoConverter
是逻辑决定,同时添加了反应性支持,因为我们不需要复制代码。唯一的限制是DBRef
分辨率,它不符合反应性执行模型。
要支持反应性 DBRef
s,需要将转换器分为几个位,整个关联处理需要大修。
参考:https://jira.spring.io/browse/datamongo-2146
建议
将参考作为键/id在您的域模型中,并根据需要查找这些。zipWith
和flatMap
是适当的操作员,具体取决于您要存档的内容(使用参考,仅查找参考的模型(。
相关注意:反应性弹簧数据mongoDB部分带有降低的功能集。上下文Spel扩展是一个不支持的功能,因为这些组件假设了命令编程模型,因此同步执行。
在第一点,我终于实现了自己想要的事情:
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;
})
);
}
在我的情况下,我已经使用以下内容来管理此问题:
- 我的实体是:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "post")
public class Post implements Serializable {
private static final long serialVersionUID = -6281811500337260230L;
@EqualsAndHashCode.Include
@Id
private String id;
private Date date;
private String title;
private String body;
private AuthorDto author;
private Comment comment;
private List<Comment> listComments = new ArrayList<>();
private List<String> idComments = new ArrayList<>();
}
- 我的控制器是:
@GetMapping(FIND_POST_BY_ID_SHOW_COMMENTS)
@ResponseStatus(OK)
public Mono<Post> findPostByIdShowComments(@PathVariable String id) {
return postService.findPostByIdShowComments(id);
}
- 最后但不是我的服务(这是解决方案(:
public Mono<Post> findPostByIdShowComments(String id) {
return postRepo
.findById(id)
.switchIfEmpty(postNotFoundException())
.flatMap(postFound -> commentService
.findCommentsByPostId(postFound.getId())
.collectList()
.flatMap(comments -> {
postFound.setListComments(comments);
return Mono.just(postFound);
})
);
}
public Flux<Comment> findCommentsByPostId(String id) {
return postRepo
.findById(id)
.switchIfEmpty(postNotFoundException())
.thenMany(commentRepo.findAll())
.filter(comment1 -> comment1.getIdPost()
.equals(id));
}
谢谢,这有很大帮助。这是我的解决方案:
public MappingMongoConverter mappingMongoConverter(MongoMappingContext mongoMappingContext) {
MappingMongoConverter converter = new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mongoMappingContext);
converter.setTypeMapper(new DefaultMongoTypeMapper(null));
converter.setCustomConversions(mongoCustomConversions());
return converter;
}
诀窍是使用noopdbrefresolver.insance