Search code examples
springmongodbmongodb-queryspring-data-mongodb

Converting mongoshell projection to Spring MongoTemplate projection


Given following mongoshell query - which works fine

[
  {
    '$match': {
      'id': '1'
    }
  }, {
    '$graphLookup': {
      'from': 'pages', 
      'startWith': '$cID', 
      'connectFromField': 'parent', 
      'connectToField': 'cID', 
      'as': 'result', 
      'depthField': 'level'
    }
  }, {
    '$unwind': {
      'path': '$result', 
      'preserveNullAndEmptyArrays': true
    }
  }, {
    '$sort': {
      'result.level': 1
    }
  }, {
    '$group': {
      '_id': '$id', 
      'result': {
        '$push': '$result'
      }
    }
  }, {
    '$project': {
      'result': {
        'id': 1, 
        'cID': 1, 
        'level': 1
      }
    }
  }
]

How do I achieve the projection using the Spring MongoTemplate and the its given DSL? Given the source and the AggregationTests provided by the github repo, I could be

project().and("result").nested(Fields.fields("id","cID","level")

which just returns an empty result list.


Solution

  • I didn't come up with a solution to make it work with the MongoTemplate directly. As I'm already using the MongoRepository given by Spring Data, creating an aggregation query is quite straightforward.

    public interface Repository extends MongoRepository<Object, String> {
      @Aggregation(pipeline = {
        "{'$match': {'cID': '?0'}}",
        "{'$graphLookup': {'from': 'pages', 'startWith': '$cID', 'connectFromField': 'cID', 'connectToField': 'parent', 'as': 'result', 'depthField': 'level'}}",
        "{'$unwind': {'path': '$result', 'preserveNullAndEmptyArrays': true}}",
        "{'$sort': {'result.level': -1}}",
        "{'$group': {'_id': '$id', 'result': {'$push': '$result'}}}",
        "{'$project': {'cID_list': '$result.cID', 'result': {'level': 1, 'cID': 1, 'id': 1}}}"
      })
      AggregationResults<Map<?, List<String>>> getChildrencIDs(final String cID);
    }