如何为复合 类 实施 MongoDB 编解码器?
How can I implement MongoDB Codecs for composite classes?
我正在使用 MongoDB 及其反应流 Java 驱动程序(在 Spring 启动项目中)编写现有的数据库访问模块。一些对象以复合方式存储在数据库中,仅存储引用 ID,然后从数据库中获取对象时 assembled(参见示例代码)。我正在使用编解码器来创建 Java 对象,但我不确定如何以复合方式制作东西。
以前使用解决方案的同步驱动程序只是逐个字段解析从 MongoDB 返回的文档,并在需要为程序集执行数据库查找时调用适当的服务。由于此解决方案很快变得完全无法管理,因此我决定使用 MongoDB 编解码器将文档直接解析为 Java 对象。但是,我不确定如何使用编解码器来做同样的事情,因为它们似乎不允许我连接到数据库以在对象创建时获取适当的数据,并且在创建后对这些对象进行额外的获取和手动设置似乎效率低下而不是真正正确的方法。
MongoDB 规则集合示例:
{
"_id": {
"$oid": "5afa865b613640f83206e23e"
},
"id": "R2",
"typeId": "RT1",
"name": "example rule",
}
RuleType 集合示例:
{
"_id": {
"$oid": "5afa865c613640f83206e260"
},
"id": "RT1",
"name": "Example rule type",
}
Rule.java
public Class Rule {
private id;
private name;
private RuleType ruleType;
// Constructors, setters, getters, etc.
}
RuleType.java
public Class Rule {
private id;
private name;
// Constructors, setters, getters, etc.
}
RuleDbService.java
public class RuleDbService {
private final MongoCollection<Rule> ruleCollection;
private final ObservableSubscriber<Rule> subscriber = new ObservableSubscriber<>();
public RuleDbService(final MongoDbAdapter mongoDbAdapter) {
this.ruleCollection = mongoDbAdapter.getCollection("rules", Rule.class);
}
public Optional<Rule> findFirst() {
this.ruleCollection.find().first().subscribe(this.subscriber);
return Optional.of(this.subscriber.get())
}
RulesCodec.java
public class RulesCodec implements Codec<Rule> {
private final Codec<Document> documentCodec;
public RulesCodec() {
this.documentCodec = new DocumentCodec();
}
public RulesCodec(final Codec<Document> codec) {
this.documentCodec = codec;
}
@Override
public Rule decode(final BsonReader reader, final DecoderContext decoderContext) {
final Document document = this.documentCodec.decode(reader, decoderContext);
final Rule rule = new Rule();
rule.setId(document.getString("id"));
// rule.setType() <- How to do this? Can I call to some findById(id) function in RuleTypeDbService from here?
rule.setName(document.getString("name"));
return rule;
}
@Override
public void encode(final BsonWriter writer, final Rule value, final EncoderContext encoderContext) {
final Document document = new Document();
final String ruleId = value.getId();
final String name = value.getName();
final String typeId = (value.getType() != null) ? value.getType().getId() : null;
if (ruleId != null) {
document.put("id", ruleId);
}
if (name != null) {
document.put("name", name);
}
if (typeId != null) {
document.put("typeId", typeId);
}
this.documentCodec.encode(writer, document, encoderContext);
}
@Override
public Class<Rule> getEncoderClass() {
return Rule.class;
}
}
我希望 RuleDbService 能够 assemble 包含 ruleType 的规则,方法是在数据库中查找它,而不是用空字段返回它,而我必须手动进行外部查找和设置在编解码器解析或其他一些解决方法之后键入。最好的方法是什么?
注意:不幸的是,我不能以任何方式修改数据库或模型结构,所以我不能使用任何 ORM 框架,例如 Morphia,它需要来自 MongoDb 的唯一 id 字段在 [=54= 中表示] 模型,所以我必须手动解码文件。
您可能会考虑使用 $lookup
的聚合。 https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
我正在使用 MongoDB 及其反应流 Java 驱动程序(在 Spring 启动项目中)编写现有的数据库访问模块。一些对象以复合方式存储在数据库中,仅存储引用 ID,然后从数据库中获取对象时 assembled(参见示例代码)。我正在使用编解码器来创建 Java 对象,但我不确定如何以复合方式制作东西。
以前使用解决方案的同步驱动程序只是逐个字段解析从 MongoDB 返回的文档,并在需要为程序集执行数据库查找时调用适当的服务。由于此解决方案很快变得完全无法管理,因此我决定使用 MongoDB 编解码器将文档直接解析为 Java 对象。但是,我不确定如何使用编解码器来做同样的事情,因为它们似乎不允许我连接到数据库以在对象创建时获取适当的数据,并且在创建后对这些对象进行额外的获取和手动设置似乎效率低下而不是真正正确的方法。
MongoDB 规则集合示例:
{
"_id": {
"$oid": "5afa865b613640f83206e23e"
},
"id": "R2",
"typeId": "RT1",
"name": "example rule",
}
RuleType 集合示例:
{
"_id": {
"$oid": "5afa865c613640f83206e260"
},
"id": "RT1",
"name": "Example rule type",
}
Rule.java
public Class Rule {
private id;
private name;
private RuleType ruleType;
// Constructors, setters, getters, etc.
}
RuleType.java
public Class Rule {
private id;
private name;
// Constructors, setters, getters, etc.
}
RuleDbService.java
public class RuleDbService {
private final MongoCollection<Rule> ruleCollection;
private final ObservableSubscriber<Rule> subscriber = new ObservableSubscriber<>();
public RuleDbService(final MongoDbAdapter mongoDbAdapter) {
this.ruleCollection = mongoDbAdapter.getCollection("rules", Rule.class);
}
public Optional<Rule> findFirst() {
this.ruleCollection.find().first().subscribe(this.subscriber);
return Optional.of(this.subscriber.get())
}
RulesCodec.java
public class RulesCodec implements Codec<Rule> {
private final Codec<Document> documentCodec;
public RulesCodec() {
this.documentCodec = new DocumentCodec();
}
public RulesCodec(final Codec<Document> codec) {
this.documentCodec = codec;
}
@Override
public Rule decode(final BsonReader reader, final DecoderContext decoderContext) {
final Document document = this.documentCodec.decode(reader, decoderContext);
final Rule rule = new Rule();
rule.setId(document.getString("id"));
// rule.setType() <- How to do this? Can I call to some findById(id) function in RuleTypeDbService from here?
rule.setName(document.getString("name"));
return rule;
}
@Override
public void encode(final BsonWriter writer, final Rule value, final EncoderContext encoderContext) {
final Document document = new Document();
final String ruleId = value.getId();
final String name = value.getName();
final String typeId = (value.getType() != null) ? value.getType().getId() : null;
if (ruleId != null) {
document.put("id", ruleId);
}
if (name != null) {
document.put("name", name);
}
if (typeId != null) {
document.put("typeId", typeId);
}
this.documentCodec.encode(writer, document, encoderContext);
}
@Override
public Class<Rule> getEncoderClass() {
return Rule.class;
}
}
我希望 RuleDbService 能够 assemble 包含 ruleType 的规则,方法是在数据库中查找它,而不是用空字段返回它,而我必须手动进行外部查找和设置在编解码器解析或其他一些解决方法之后键入。最好的方法是什么?
注意:不幸的是,我不能以任何方式修改数据库或模型结构,所以我不能使用任何 ORM 框架,例如 Morphia,它需要来自 MongoDb 的唯一 id 字段在 [=54= 中表示] 模型,所以我必须手动解码文件。
您可能会考虑使用 $lookup
的聚合。 https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/