0
MatchOperation matchDepartmentStage = Aggregation.match(Criteria.where("department").is("DEPT_A"));
ProjectionOperation projectEmployeeStage = Aggregation.project()
        .andExpression("concat(emp_name,'-', emp_age)").as("emp_name_age");
Criteria criteriaNameAndAge = new Criteria();
List<Pair<String,String>> nameAndAgeList = new ArrayList<>();
nameAndAgeList.add(Pair.of("abcd", "30"));

nameAndAgeList.forEach(nameAndAge -> {
    criteriaNameAndAge.and("emp_name_age").ne(nameAndAge.getFirst()+"-"+nameAndAge.getSecond());
});
MatchOperation matchNameAndAgeStage = Aggregation.match(criteriaNameAndAge);
SortOperation sortStage = Aggregation.sort(Sort.Direction.ASC, "dateCreated");

Aggregation aggregation = Aggregation.newAggregation(matchDepartmentStage,
        projectEmployeeStage,
        matchNameAndAgeStage,
        sortStage);

Employee employee = null;
AggregationResults<Employee> employeeAggregationResults =
            mongoTemplate.aggregate(aggregation, "employees", Employee.class);

My attempt is to do as following

  1. Filter employees by department

  2. From the result, for every employee, project a new field that combines 2 fields, emp_name & emp_age to emp_name_age

  3. Create a dynamic match criteria to match this new field

  4. Sort by date

It does not work as expected. Error is invalid reference 'dateCreated'

Sample documents:


{ "_id" : "1", "department" : "DEPAT_A", "name" : "abcd", "age" : "30", "dateCreated" : ISODate("2019-12-31T10:30:00Z"), "_class" : "org.example.Employee" }
{ "_id" : "2", "department" : "DEPAT_A", "name" : "abcd", "age" : "40", "dateCreated" : ISODate("2019-12-31T10:30:00Z"), "_class" : "org.example.Employee" }

EDIT

changed a few lines and it is working. 2 problems identified.

  1. Project has to mention the fields. In my case, name all fields, which I didnt like.

  2. Use nin instead of ne

ProjectionOperation projectEmployeeStage = Aggregation.project(Field.fields("department","name","age","dateCreated"))
        .andExpression("concat(emp_name,'-', emp_age)").as("emp_name_age");
List<String> nameAges = nameAndAgeList.stream()
                .map(nameAge -> nameAge.getFirst()+"-"+nameAge.getSecond())
                .collect(Collectors.toList());
Criteria criteriaNameAndAge = new Criteria("emp_name_age").nin(nameAges);
MatchOperation matchNameAndAgeStage = Aggregation.match(criteriaNameAndAge);
Winster
  • 943
  • 10
  • 28
  • 1. put a sample document which you have, 2. what is nameAndAgeList? where is it defined? – pvpkiran Apr 23 '20 at 14:35
  • I added the details – Winster Apr 23 '20 at 14:42
  • I fixed it. There were 2 issues. Project has to mention the field names. There is no way to select all fields by default. Hence name each of the field. Next dynamic criteria has to be adjusted to use **nin** instead of **ne** for each condition. – Winster Apr 23 '20 at 15:11

0 Answers0