CounterFlame
CounterFlame

Reputation: 1632

Spring Data MongoDB - ignore empty objects

I'm using Spring Data with a MongoDB to save some documents. When saving documents, I would like that Mongo does not contain empty objects. (How) can this be achieved?

Say I have the following main class:

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

    private String title;
    private SubDoc subDoc;
}

that contains an object of the following class:

public class SubDoc {

    private String title;
    private String info;

}

Now if I would try to save the following object:

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

Note: in reality I do not control the fact that the SubDoc is set like this. It can either be empty or filled in. What I want is that if an element's properties/fields are all NULL, it will not be stored in mongo at all. This results in something like this in mongo:

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

What I would like is that if an element contains only null properties, they aren't saved at all, so for the above example I would want the following result:

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

Saving of documents is done with the help of a repository as following:

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

    // save inherited

}

Thanks in advance.

Upvotes: 2

Views: 6477

Answers (1)

Orest
Orest

Reputation: 6748

One thing you can do here is to write your custom converter for 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());
        }
    }
}

You can register it in @Configuration file for example:

@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;
    }

}

If you don't want to write a custom converter for your object toy can use default one and and modify it a bit.

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

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

mongoTemplate().save(document);

Actually it's not the best way. As guys wrote empty object should be stored as {}, but converter can help you with your case.

Upvotes: 2

Related Questions