How to add default criteria to all the queries by default in mongo spring boot

Viewed 384

I have a requirement to soft delete documents in a given MongoDB collection. For that, I use a boolean called deleted. So now when I am retrieving data from the database, I have to always mention taking the data where the deleted=false.

Eg:

public Organization findOrgById(String id) {
    Query query = new Query();
    Criteria criteria = Criteria.where(Constants.ENTITY_ID).is(id)
            .and(Constants.DELETED).is(false);
    query.addCriteria(criteria);
    Organization res = mongoTemplate.findOne(query, Organization.class);
    return res;
}

Is there a way to specify that always all the criteria to add deleted=false by default without mentioning it in the code itself? In Hibernate core there is an annotation @Where but it is not working with mongo documents.

1 Answers

I think the best way to do this is extend the MongoTemplate class that will add your deleted=false condition to all Find queries.

Here is an example of how to do it with one method used to execute findOne queries:

public class ExtendedMongoTemplate extends MongoTemplate {

    private static final Document DELETED_CRITERIA_DOC = Criteria.where(Constants.DELETED).is(false)
        .getCriteriaObject();

    @Override
    protected <T> T doFindOne(
            String collectionName,
            Document query,
            Document fields,
            CursorPreparer preparer,
            Class<T> entityClass) {
        query.putAll(DELETED_CRITERIA_DOC);
        return super.doFindOne(collectionName, query, fields, preparer, entityClass);
    }
    ...
}

This method is called in the method doFindOne(Query query, Class<?> entityClass) (the last one delegates executing

Other methods to override are:

protected <S, T> List<T> doFind(String collectionName, Document query, Document fields,
    Class<S> entityClass, CursorPreparer preparer);

protected <T> T doFindAndRemove(String collectionName, Document query, Document fields,
    Document sort, @Nullable Collation collation, Class<T> entityClass);

protected <T> T doFindAndModify(String collectionName, Document query, Document fields, Document sort,
    Class<T> entityClass, UpdateDefinition update, @Nullable FindAndModifyOptions options);

protected <T> T doFindAndReplace(String collectionName, Document mappedQuery, Document mappedFields,
    Document mappedSort, com.mongodb.client.model.Collation collation, Class<?> entityType,
    Document replacement, FindAndReplaceOptions options, Class<T> resultType);

These methods execute queries at low-level, so they accept BSON-documents with the query criteria, not Spring's criteria. If you do this, the Find-methods will add an additional criteria to all you queries.

You also can override methods findOne, find, findAndModify and so on in a similar manner, but there are a lot of these methods that all use doFind* methods. Thus overriding doFind* will lead to work with all Find-queries. And don't forget override also findById (it also uses doFindOne internally).

By the way, @Where annotation is from Hibernate, but Spring Data Mongo doesn't use them. It requires its own annotations to work with your entities.

Related