Jamie Cramb
Jamie Cramb

Reputation: 115

Build dynamic queries with Spring Data MongoDB Criteria

I would like to run a bulk delete operation on a list of documents in MongoDB that have been selected by the user in the UI so I need to dynamically build a query that looks like the following (the or clause expands for every document selected):

{
    $and: [
        {
            "contentType": "application/vnd.sometype"
        },
        {
            $or: [
                {
                    "metadata.name": "someName",
                    "metadata.version": "someVersion"
                },
                {
                    "metadata.name": "someOtherName",
                    "metadata.version": "someOtherVersion"
                }
            ]
        }
    ]
},
Fields: null,
Sort: null

Just now I'm using string concatenation to achieve this.

Is it possible to build this query with the Spring Data MongoDB Criteria Builder (org.springframework.data.mongodb.core.query.Criteria)?

Upvotes: 6

Views: 34094

Answers (2)

Sandun Susantha
Sandun Susantha

Reputation: 1140

Here we need to build new query and embed the criteria to the built new query. And also, we have to create a list of criteria using some criteria for embed to the query. Here my example is providing a list of metadata and we don't know the name of parameter which will send for us. So, The solution is as given follow.

List<Criteria> criterias = new ArrayList<>();

    for (MetaData metaData : newDoc.getMetaData()) {
        Criteria dynamicCriteria = Criteria.where("metaData.key").is(metaData.getKey()).andOperator(Criteria.where("metaData.value").is(metaData.getValue()));
        criterias.add(dynamicCriteria);
    }

    Criteria criteria = new Criteria().andOperator(criterias.toArray(new Criteria[criterias.size()]));

    Query searchQuery = new Query(criteria);

    List<Document> documents = mongoTemplate.find(searchQuery, Document.class);

Upvotes: 2

Artem Bilan
Artem Bilan

Reputation: 121272

Doesn't this work for you?

Criteria criteria = Criteria.where("contentType").is("application/vnd.sometype");

List<Criteria> docCriterias = new ArrayList<Criteria>(docs.size());

for (Document doc: docs) {
    docCriterias.add(Criteria.where("metadata.name").is(doc.getName())
                               .and("metadata.version").is(doc.getVersion()));
}

criteria = criteria.orOperator(docCriterias.toArray(new Criteria[docs.size()]));

?

Upvotes: 13

Related Questions