Search code examples
javaspringmongodbspring-dataspring-mongo

$filter inside $project MongoDB Using Spring Data


I have a subdocument that is an array of a parent document. "devices"

In that array I've got a property which is a Date property.

I want to find the parents documents who contains the child subdocuments by determinated date like this:

{
"_id" : ObjectId("5818fa596969a1339093a7da"),
"fecha" : ISODate("2016-11-01T05:00:00.000Z"),
"spot" : "5808e3926969a126c8365c94",
"devices" : [ 
    {
        "evaluationDate" : ISODate("2016-11-01T20:26:00.000Z"),
        "seenTimesCounter" : 0,
        "category" : "PRE_PASAJERO",
        "status" : "NO_CONECTADO"
    }, 
    {
        "evaluationDate" : ISODate("2016-11-01T20:26:00.000Z"),
        "seenTimesCounter" : 0,
        "category" : "PRE_PASAJERO",
        "status" : "NO_CONECTADO"
    },  
    {
        "evaluationDate" : ISODate("2016-11-01T20:26:00.000Z"),
        "seenTimesCounter" : 0,
        "category" : "PRE_PASAJERO",
        "status" : "NO_CONECTADO"
    }, 
    {
        "evaluationDate" : ISODate("2016-11-01T20:26:00.000Z"),
        "seenTimesCounter" : 0,
        "category" : "PRE_PASAJERO",
        "status" : "NO_CONECTADO"
    }, 
    {
        "evaluationDate" : ISODate("2016-11-01T20:26:00.000Z"),
        "seenTimesCounter" : 0,
        "category" : "PRE_PASAJERO",
        "status" : "NO_CONECTADO"
    }, 
    {
        "evaluationDate" : ISODate("2016-11-01T20:26:00.000Z"),
        "seenTimesCounter" : 0,
        "category" : "PRE_PASAJERO",
        "status" : "NO_CONECTADO"
    }
]
}

I have tried this on mongo shell (and the query is good, it Returns what I want):

db.getCollection('spotMovimientos').aggregate([
{$match:{'devices.evaluationDate':ISODate("2016-11-01T20:26:00.000Z")}},
{$project: {
'devices':{$filter:{
    input:'$devices',
    as:'device',
    cond: {$eq: ['$$device.evaluationDate', ISODate("2016-11-01T20:26:00.000Z")]}
    }
} }
}
])

Can anyone elaborate on this? I need help to convert this to SPRING DATA

Thank you.


Solution

  • I managed to solve my problem with the Spring boot Version 1.4.1.RELEASE and I did this:

    Aggregation aggregation = newAggregation(
                match(Criteria.where("devices.evaluationDate").is(date)),
                project().and(new AggregationExpression() {
                    @Override
                    public DBObject toDbObject(AggregationOperationContext aggregationOperationContext) {
                        DBObject filterExpression = new BasicDBObject();
                        filterExpression.put("input", "$devices");
                        filterExpression.put("as", "device");
                        filterExpression.put("cond", new BasicDBObject("$eq", Arrays.<Object> asList("$$device.evaluationDate", date)));
                        return new BasicDBObject("$filter", filterExpression);
                    }
                }).as("devices")
        );
    
        AggregationResults<SpotMovimientos> list = mongoOperations.aggregate(aggregation,
                MyClass.class, MyClass.class);
    

    I elaborated based on this: Does Spring Data MongoDb support $filter array aggregations operator?

    My project was on Spring boot 1.4.0.RELEASE but that version didnt have the AggregationExpression interface PUBLIC, so i just updated to 1.4.1.RELEASE and i did work.