0

I have a collection with documents of the following structure:

{
    "category": "movies",
    "movies": [
        {
          "name": "HarryPotter",
          "language": "english"
        },
        {
            "name": "Fana",
            "language": "hindi"
        }
    ]
}

I want to query with movie name="fana" and the response sholud be

{
    "category": "movies",
    "movies": [
        {
            "name": "HarryPotter",
            "language": "english"
        }
    ]
}

How do I get the above using spring mongoTemplate?

s7vr
  • 73,656
  • 11
  • 106
  • 127

3 Answers3

0

$unwind of mongodb aggregation can be used for this.

db.Collection.aggregate([{
   {$unwind : 'movies'},
   {$match :{'movies.name' : 'fana'}}
  }])

You can try the above query to get required output.

azhar
  • 1,709
  • 1
  • 19
  • 41
0

You can try something like this.

Non-Aggregation based approach:

public MovieCollection getMoviesByName() {
    BasicDBObject fields = new BasicDBObject("category", 1).append("movies", new BasicDBObject("$elemMatch", new BasicDBObject("name", "Fana").append("size", new BasicDBObject("$lt", 3))));
    BasicQuery query = new BasicQuery(new BasicDBObject(), fields);
    MovieCollection groupResults = mongoTemplate.findOne(query, MovieCollection.class);
    return groupResults;
}   

Aggregation based approach:

import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import static org.springframework.data.mongodb.core.query.Criteria.where;

public List<BasicDBObject> getMoviesByName() {
     Aggregation aggregation = newAggregation(unwind("movies"), match(where("movies.name").is("Fana").and("movies.size").lt(1)),
        project(fields().and("category", "$category").and("movies", "$movies")));
     AggregationResults<BasicDBObject> groupResults = mongoTemplate.aggregate(
        aggregation, "movieCollection", BasicDBObject.class);
     return groupResults.getMappedResults();
}
s7vr
  • 73,656
  • 11
  • 106
  • 127
0

Above approaches provides you a solution using aggregation and basic query. But if you dont want to use BasicObject below code will perfectly work:

Query query = new Query()
query.fields().elemMatch("movies", Criteria.where("name").is("Fana"));
List<Movies> movies = mongoTemplate.find(query, Movies.class);

The drawback of this query is that it may return duplicate results present in different documents, since more than 1 document may match this criteria. So you can add _id in the criteria like below:

Criteria criteria = Criteria.where('_id').is(movieId)
Query query = new Query().addCriteria(criteria)
query.fields().elemMatch("movies", Criteria.where("name").is("Fana"));
query.fields().exclude('_id')
List<Movies> movies = mongoTemplate.find(query, Movies.class);

I am excluding "_id" of the document in the response.

Sachin Kumar
  • 169
  • 2
  • 8