【问题标题】:Spring MongoDB manual referenceSpring MongoDB 手册参考
【发布时间】:2020-10-01 21:47:20
【问题描述】:

我正在尝试在 Spring MongoDB 中创建手动引用,以简单地将 ObjectId 存储在引用字段中并仅在需要时填充它。 (即没有 DBRef)

但是,我无法找到有关如何正确实现此功能的文档。

假设我有一个像这样的简单模型:


@Document(collection = "person")
public class Person{

    @Id
    private String id;

    ... other attributes

    //This is a reference to Address model
    private ObjectId address;

}

和

@Document(collection = "address")
public class Address{

    @Id
    private String id;

    ... other attributes

}

如何在此处创建手动引用以仅将地址模型的 ID 存储在 Person 中,然后仅在需要时填充?

更新: 澄清一下,我们已经有很多以前使用 Mongoose 插入的数据库文档,其中模型 A 包含一个引用模型 B 的 ObjectId。使用 mongoose,我们可以在需要时在这些文件上调用 .populate。那么当我们保存文档时,Mongoose 只保存了 ObjectId。

基本上我试图在 Spring 中实现一个类似的系统。 我创建了一个自定义转换器,在加载数据时将 ObjectId 转换为特定类型,但此解决方案没有帮助,因为它不会在保存时将 Model 转换为 ObjectId。

这是我们需要的:

  1. 参考字段仅包含一个 ObjectID 或一个 ID 数组。
  2. 我们只能在需要时填充该字段。
  3. 我们可以修改填充的字段并调用 save 方法,这会更新两个文档并仅将 ObjectId 保存在引用字段中。
  4. 某些文档的参考字段可以为空。
  5. 添加新引用时,我们可以使用 ObjectID 或对象。无论哪种情况,都应仅使用 ObjectID。

同样,这正是 Mongoose 在 Javascript 中的工作方式,也是我们目前正在使用的。

我正在寻找详细的答案或某种教程来解释如何实现这一点,因为我无法使用手动参考找到任何示例,这很奇怪,因为手动参考更受欢迎,而且推荐的方法。

【问题讨论】:

    标签: java spring spring-boot spring-data-mongodb


    【解决方案1】:

    使用 @DbRef 并具有相同的字段名称,只是将 ObjectId 列表引用为模型上的另一个字段。

    public class ModelModelListener extends AbstractMongoEventListener<Model> {
        @Override
        public void onBeforeSave(BeforeSaveEvent<Model> event) {
            final Model source = event.getSource();
            final Document document = event.getDocument();
            final List<Model> modelList = source.getModelList();
            final List<ObjectId> modelIdList = source.getModelIdList();
            if (document != null)
                document.put("modelList", modelList != null ? toIdList(modelList) : modelIdList);
        }
    
        @Override
        public void onAfterConvert(AfterConvertEvent<Model> event) {
            final Model source = event.getSource();
            final Document document = event.getDocument();
            if (document != null)
                source.setModelIdList(document.getList("modelList", ObjectId.class));
        }
    }
    
    @Data // Lombok getter setter
    @Document
    public class Model {
    
        @Field("modelList")
        @DBRef(lazy = true)
        private List<Model> modelList;
    
        @Field
        private List<ObjectId> modelIdList;
    }
    

    或者您可以在更新或插入时使用带有条件的 MongoTemplate。

    final Update update = new Update();
    update.push("field", modelB.getId());
    mongoTemplate.updateFirst(query, update, ModelA.class);
    

    【讨论】:

    • 这不会将modelList和modelIdList都插入db吗?我只想要 db 上的 modelIdList。
    • @Aiden 我已经更新了示例以访问有关适当操作的文档。看到 modelIdList 只是 DB 文档中相同字段的表示。
    【解决方案2】:

    你可以修改查找方法。

    db.person.find({...parameters...}).forEach(function(persons) {
      persons.forEach(p => {
         db.address.find({person: p.id}).forEach(function(address) {
         person.address = address.id;
      });
    });
    

    这样做时,您始终传递关系 ID。 我相信没有DBRef是不行的。

    【讨论】:

    • 确实有道理;然而,我们已经在数据库中拥有的文档之前是使用 Mongoose 插入的,其中模型 A 包含一个引用模型 B 的 ObjectId。使用 mongoose,我们可以在需要时调用 .populate 。基本上,我正在尝试找到一种方法来使用 Spring MongoDB 实现类似的事情
    • 那么...为什么不使用 DBRef?如果您已映射属性,则应将它们映射为对象。
    • 我将使用姑息性解决方案编辑我的解决方案。根据我的研究,没有办法通过映射来做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    相关资源
    最近更新 更多