Spring MongoRepository Получить счетчик агрегации - PullRequest
0 голосов
/ 21 декабря 2018

Я использую релиз spring-data-mongodb 2.0.8, и мне нужно было рассчитать количество сотрудников в отделе конкретной компании.Ниже приведен эквивалентный запрос, если он будет запрошен в MySQL.

MySQL

select 
    departmentId, count(employeeId)
from employees
where companyCode = 'ACME'
group by departmentId

MongoDb

db.employees.aggregate([
    {
      $match: {
        "companyCode": "ACME"
      }
    },
    {
        "$group" : {
            _id:"$departmentId", 
            count:{$sum:1}
        }
    }
])

Моя проблема в том, как мне преобразовать это в код MongoRepository, похожий на JPA.Пожалуйста, смотрите код ниже:

public interface EmployeeDao extends MongoRepository<Employee, String> {

    Employee findFirstByName(String name);
    Employee findFirstByDepartmentId(String departmentId);
    List<Employee> findEmployeesByCompanyCodeAndDepartmentId(String companyCode, String departmentId);
    List<Employee> findEmployeesByDepartmentId(String departmentId);
    Long countByCompanyCode(String companyCode);
    Long countByDepartmentId(String departmentId);

    // FIXME:
    /*  How will I convert this into MongoRepository code, like above?

        MySQL:
        select 
            departmentId, count(employeeId)
        from employees
        where companyCode = 'ACME'
        group by departmentId

        MongoDb:
        db.employees.aggregate([
            {
              $match: {
                "companyCode": "ACME"
              }
            },
            {
                "$group" : {
                    _id:"$departmentId", 
                    count:{$sum:1}
                }
            }
        ])
    */

}

Обновление (что работает для моего случая):

Я нашел следующий код, работающий для моего случая, но я неконечно, если это приемлемо или есть лучший способ сделать это (по лучшей практике).

...
        String companyCode =  ACME";
        MatchOperation filterCompany = match(new Criteria("companyCode").is(companyCode));
        GroupOperation groupCountByDepartmentId = group("departmentId").count().as("total");
        SortOperation sortByCountDesc = sort(new Sort(Sort.Direction.DESC, "total"));
        ProjectionOperation projectToMatchModel = project()
                .andExpression("_id").as("departmentId")
                .andExpression("total").as("count");
        Aggregation aggregation = Aggregation
                .newAggregation(filterCompany, groupCountByDepartmentId, sortByCountDesc, projectToMatchModel);
        AggregationResults<DepartmentCount> groupResults =
                m_mongoTemplate.aggregate(aggregation, Employee.class, DepartmentCount.class);
        List<DepartmentCount> result = groupResults.getMappedResults();
...

DepartmentCount:

public class DepartmentCount {

    private String departmentId;
    private Integer count;

    // getters and setters

}

Спасибо!

1 Ответ

0 голосов
/ 21 декабря 2018

Вы можете использовать AggregationOperations, как показано ниже:

ApplicationContext ctx = new AnnotationConfigApplicationContext(MongoConfig.class);
MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate"); 

List<AggregationOperation> aggregationOperations = new ArrayList<AggregationOperation>();
aggregationOperations.add(new MatchOperation(Criteria.where("country").is("tigo")));
aggregationOperations.add(new UnwindOperation(Fields.field("myDetails")));
aggregationOperations.add(new MatchOperation(Criteria.where("myDetails.type").is("health")));
aggregationOperations.add(new SortOperation(new Sort(Sort.Direction.ASC, "myDetails.datetime")));
AggregationResults<AggregateFactoryResult> result = mongoOperation.aggregate(new Aggregation(aggregationOperations), "gui_data", AggregateFactoryResult.class)

Пожалуйста, проверьте эту ссылку

...