1
votes

I have requirement to filter document in mongodb using spring data which contains nexted arrays of arrays. I am using following aggregation query on mongo shell and it is working fine. But when I am firing that through springdata aggregation operation, I am gettin empty response. Working mongo query is:

db.searchResource.aggregate({$match:{"_id" : ObjectId("53cf4e3dae92ac6561807f6d")}},{$project:{"rssSearchResponse.journeys":1}},{$unwind : "$rssSearchResponse.journeys"},{$match:{"rssSearchResponse.journeys.stops":0}});

Spring data code which I am using and s not working:

TypedAggregation<SearchResource> aggregation = Aggregation.newAggregation(SearchResource.class, Aggregation.match(new Criteria("_id").is(new ObjectId(searchId))),
                Aggregation.project("rssSearchResponse.journeys"),
                Aggregation.unwind("rssSearchResponse.journeys"),
                Aggregation.match(new Criteria("rssSearchResponse.journeys.stops").is(0))
                );
AggregationResults<SearchResource> result = mongoOperations.aggregate(aggregation, JourneyInformation.class);

I have tried breaking this aggregate function and it is able to project rssSearchResponse.journeys but after $unwind it returns empty result.

Any help is highly appreciated.

2
Have you tried the latest 1.4.2.RELEASE? - Oliver Drotbohm
Thanks Oliver it worked by updating version to 1.4.x. - Developer G

2 Answers

3
votes

How about:

@Test
public void foo() {

    mongoTemplate.dropCollection(RssSearchResponse.class);

    RssSearch rs = new RssSearch();
    rs.id  = "123";
    rs.rssSearchResponse = new RssSearchResponse(
            new Journey[] {new Journey("A", 1),new Journey("B", 0),new Journey("C", 0),new Journey("D", 1)}
    );

    mongoTemplate.insert(rs);

    Aggregation agg = newAggregation(RssSearch.class, //
          match(where("_id").is(rs.id)) //
        , project("rssSearchResponse.journeys") //
        , unwind("journeys") //
        , match(where("journeys.stops").is(0)) //
    );

    AggregationResults<DBObject> result = mongoTemplate.aggregate(agg, RssSearch.class, DBObject.class);
    System.out.println(result);

}

static class RssSearch{
    String id;
    RssSearchResponse rssSearchResponse;
}

static class RssSearchResponse{
    Journey[] journeys;

    public RssSearchResponse(Journey[] journeys) {
        this.journeys = journeys;
    }
}

static class Journey{
    String name;
    int stops;

    public Journey(String name, int stops) {
        this.name = name;
        this.stops = stops;
    }
}

This will return B and C.

We generate the following aggregation command:

{ 
    "aggregate" : "rssSearch" 
  , "pipeline" : [ 
     { "$match" : { "_id" : "123"}} 
   , { "$project" : { "journeys" : "$rssSearchResponse.journeys"}}
   , { "$unwind" : "$journeys"}
   , { "$match" : { "journeys.stops" : 0}}
  ]
}
2
votes
 match(where("_id").is(rs.id)) 

Doesn't work in Mongo Aggregation.

You have to convert rs.id to ObjectId

match(where("_id").is(new ObjectId(rs.id)))