【问题标题】:Spring Data MongoDB - ignore empty objectsSpring Data MongoDB - 忽略空对象
【发布时间】:2017-11-11 11:00:56
【问题描述】:

我正在使用带有 MongoDB 的 Spring Data 来保存一些文档。保存文档时,我希望 Mongo 不包含空对象。 (如何)这可以实现?

假设我有以下主要课程:

@Document(collection = "main_doc")
public class MainDoc {
    @Id
    private String id;

    private String title;
    private SubDoc subDoc;
}

包含以下类的对象:

public class SubDoc {

    private String title;
    private String info;

}

现在,如果我尝试保存以下对象:

MainDoc main = new MainDoc();
main.setTitle("someTitle");
main.setSubDoc(new SubDoc());

注意:实际上我无法控制 SubDoc 是这样设置的事实。它可以是空的,也可以是填充的。我想要的是,如果一个元素的属性/字段都是 NULL,它根本不会存储在 mongo 中。 这会在 mongo 中产生类似的结果:

{
    "_id" : "5a328f9a-6118-403b-a3a0-a55ce52099f3",
    "title": "someTitle",
    "subDoc": {}
}

我想要的是,如果一个元素只包含空属性,它们根本不会被保存,所以对于上面的例子,我想要以下结果:

{
    "_id" : "5a328f9a-6118-403b-a3a0-a55ce52099f3",
    "title": "someTitle"
}

文档的保存是在存储库的帮助下完成的,如下所示:

@NoRepositoryBean
public interface MainRepo extends CrudRepository<MainDoc, String> {

    // save inherited

}

提前致谢。

【问题讨论】:

  • 不要调用main.setSubDoc(new SubDoc()); 您将其设置为空。如果您不调用它,那么它将不存在。
  • 是的,但在我的实际用例中,我无法控制那部分。我真的需要在映射期间完成它。抱歉,应该更清楚一点。
  • 那您的问题能更具体一点吗?在我看来,如果没有数据可以放在那里,你根本就不要打电话。也许您的代码中需要if
  • 事实上,我的对象是从大量嵌套查询构建到关系数据库,然后保存到 mongo DB。如果使用的嵌套对象为空,每次都必须检查,这意味着大量的检查。这就是为什么我更愿意让映射为我完成这项工作。
  • 详细信息在您的问题中Edit Your Question 并且不要发布长的 cmets。

标签: mongodb spring-data-mongodb


【解决方案1】:

您可以在这里做的一件事是为MainDoc 编写自定义转换器:

public class MainDocConverter implements Converter<MainDoc, DBObject> {
    @Override
    public DBObject convert(final MainDoc source) {
        final BasicDbObject dbObject = new BasicDBObject();
        ...
        if(/* validate is subdoc is not null and not empty */) {
            dbOject.put("subDoc", source.getSubDoc());
        }
    }
}

您可以在@Configuration文件中注册例如:

@Configuration
@EnableMongoRepositories(basePackages = {"package"})
public class MongoConfig {

    private final MongoDbFactory mongoDbFactory;

    public MongoConfig(final MongoDbFactory mongoDbFactory) {
        this.mongoDbFactory = mongoDbFactory;
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {

        final MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, getDefaultMongoConverter());
        return mongoTemplate;

    }

    @Bean
    public MappingMongoConverter getDefaultMongoConverter() throws Exception {

        final MappingMongoConverter converter = new MappingMongoConverter(
                new DefaultDbRefResolver(mongoDbFactory), new MongoMappingContext());
        converter.setCustomConversions(new CustomConversions(Arrays.asList(new MainDocConverter())));

        return converter;
    }

}

如果您不想为您的对象玩具编写自定义转换器,可以使用默认转换器并稍作修改。

final Document document = (Document) getDefaultMongoConverter().convertToMongoType(mainDoc);

if(/* validate is null or is empty */) {
    document .remove("subDoc");
}

mongoTemplate().save(document);

其实这不是最好的方法。正如人们所写的那样,空对象应存储为{},但转换器可以帮助您解决问题。

【讨论】:

  • 这会让我得到我想要的,是的,但它仍然需要大量检查。有没有办法从那个自定义转换器中首先调用默认实现,然后检查 dbObject 是否没有设置字段并在这种情况下返回 null?
  • @CounterFlame 我已经编辑了我的答案。您可以为此使用默认转换器。
猜你喜欢
  • 2019-07-02
  • 2018-07-24
  • 2015-11-13
  • 2020-05-31
  • 2015-03-23
  • 2020-10-30
  • 2015-08-03
  • 2017-01-15
  • 1970-01-01
相关资源
最近更新 更多